WindowsPE文件格式入门05.PE加载器LoadPE
https://bpsend.net/thread-316-1-1.html
LoadPE - pe 加载器 壳的前身
如果想访问一个程序运行起来的内存,一种方法就是跨进程读写内存,但是跨进程读写内存需要来回调用api,不如直接访问地址来得方便,那么如果我们需要直接访问地址,该怎么做呢?.需要把dll注进程,注进去的代码跟他在同一块进程里面,这样我们就可以直接访问这个进程的地址,但是不想注入,也不想跨进程读写地址,就直接读进程地址,有什么方法呢?如果把导入表里面加一个dll,这样很容易检查出来,模块里一遍历,就可容易看到了, 其实我们可以反其道行之,换种思路,不是往他进程里面塞东西,而是把他加载到我们进程里面.,这个时候再去访问进程内存其实就是访问我们自己的内存.
1.系统加载exe的流程
- 准备一个新的内存;
- 按照顺序把节表内容映射进内存;
- 填写导入表。
2.LoadPE的目的
- 可以在自己进程更改目标PE的内存。
3.LoadPE的重点
- 1.在自己代码前留出足够空间--目标进程的SizeofImage;
- 2.更改自己程序的ImageBase加载到目标ImageBase处:/base:0x。

这样,目标进程的PE头就占据了我们自己进程的 PE头,他的数据节就覆盖了我们自己的数据节,即目标进程的数据就会覆盖我们自己进程的数据,因此我们需要 把我们的代码往后移,给 目标进程 留出足够的空间
4.LoadPE的实现思路
- 设置我们进程的 ImageBase 和 目标进程 ImageBase 保持一致
- 我们需要把我们的代码往后移,腾出来的内存可以放目标程序
- 读目标进程的数据,按照节表拷贝数据帮他处理导入表
- 执行目标进程代码。
5.LoadPE的汇编实现
- 用winhex查看目标进程的 ImageBase 和 SizeofImage
- 新建工程,并且在工程选项设置 自己工程 的 ImageBase 与目标进程的一致
- 后移自己的代码,可以在开头定义 SizeofImage 大小的全局变量 或者通过指令 org 偏移调整指令
注意,很多 C 库函数 并不会 保存 ecx , edx 环境,自己使用前记得先保存
进程的模块基址和 数据大小可以通过 winhex看

.586 .model flat,stdcall option casemap:noneinclude windows.incinclude user32.incinclude kernel32.incinclude msvcrt.incincludelib user32.libincludelib kernel32.libincludelib msvcrt.libIMAGE_SIZE equ 20000h ;往后移的大小,即目标进程的SizeofImage.datag_szFile db "winmine.exe", 0 ;要读取的进程.codeorg IMAGE_SIZE LoadPe procLOCAL @dwImageBase:DWORD ;自己进程的模块基址LOCAL @hFile:HANDLE ;文件句柄LOCAL @hFileMap:HANDLE ;映射句柄LOCAL @pPEBuf:LPVOID ;映射文件的缓冲地址LOCAL @pDosHdr:ptr IMAGE_DOS_HEADER ;目标进程的dos头LOCAL @pNTHdr:ptr IMAGE_NT_HEADERS ;目标进程的NT头LOCAL @pSecHdr:ptr IMAGE_SECTION_HEADER ;目标进程的节表LOCAL @dwNumOfSecs:DWORD ;目标进程的节表数量LOCAL @pImpHdr:ptr IMAGE_IMPORT_DESCRIPTOR ;目标进程的导入表LOCAL @dwSizeOfHeaders:DWORD ;目标进程的选项头大小LOCAL @dwOldProc:DWORD ;旧的内存属性LOCAL @hdrZeroImp:IMAGE_IMPORT_DESCRIPTOR ;导入表结束标志,所有项全0LOCAL @hDll:HMODULE ;加载dll的句柄LOCAL @dwOep:DWORD ;进程的入口地址;判断导入表结束的标志清0invoke RtlZeroMemory, addr @hdrZeroImp, size IMAGE_IMPORT_DESCRIPTOR;自己的模块基址invoke GetModuleHandle, NULLmov @dwImageBase, eax;解析PE文件,获取表;打开文件invoke CreateFile, offset g_szFile, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL;check ....mov @hFile, eax ;保存文件句柄invoke CreateFileMapping, @hFile, NULL, PAGE_READONLY, 0, 0, NULL ;创建文件映射;checkmov @hFileMap, eax ;创建文件映射句柄invoke MapViewOfFile, @hFileMap, FILE_MAP_READ, 0, 0, 0 ;将整个文件映射进内存;check mov @pPEBuf, eax ;保存映射文件内存的地址;解析目标进程;目标进程的 dos 头mov eax, @pPEBuf mov @pDosHdr, eax;目标进程的 nt头mov esi, @pDosHdrassume esi:ptr IMAGE_DOS_HEADERmov eax, @pPEBufadd eax, [esi].e_lfanew ;获取nt头的偏移地址mov @pNTHdr, eaxmov esi, @pNTHdrassume esi:ptr IMAGE_NT_HEADERS;选项头信息mov eax, [esi].OptionalHeader.SizeOfHeaders ;获取选项头大小mov @dwSizeOfHeaders, eax;进程的入口地址 = 进程的内存偏移地址 + 模块基址mov eax, [esi].OptionalHeader.AddressOfEntryPointadd eax, @dwImageBasemov @dwOep, eax;节表 地址: 选项头地址+大小movzx eax, [esi].FileHeader.NumberOfSectionsmov @dwNumOfSecs,eaxlea ebx, [esi].OptionalHeader;获取选项头大小:用于定位节表位置=选项头地址+选项头大小movzx eax, [esi].FileHeader.SizeOfOptionalHeader ;把 word 转为 dwordadd eax, ebxmov @pSecHdr, eax ;保存节表地址;修改内存属性invoke VirtualProtect, @dwImageBase, IMAGE_SIZE, PAGE_EXECUTE_READWRITE, addr @dwOldProc;拷贝PE头 从映射内存拷贝到 自己进程的最开始处 invoke crt_memcpy, @dwImageBase, @pPEBuf, @dwSizeOfHeaders;按照节表,拷贝节区数据mov esi, @pSecHdrassume esi:ptr IMAGE_SECTION_HEADERxor ecx, ecx.while ecx < @dwNumOfSecs ;遍历节表;目标mov edi, @dwImageBaseadd edi, [esi].VirtualAddress ;获取节的内存地址 + 模块地址 就是内存中的绝对地址;源mov ebx, @pPEBufadd ebx, [esi].PointerToRawData ;获取指定进程的节数据的偏移地址 映射的首地址 + 文件偏移地址;大小[esi].SizeOfRawData;拷贝 注意,很多 C 库函数 并不会 保存 ecx ,edx 环境,自己使用前记得先保存push ecxpush edxinvoke crt_memcpy, edi, ebx, [esi].SizeOfRawData ;将目标进程的节数据拷贝进自己的进程pop edxpop ecxinc ecx ;计数++add esi, size IMAGE_SECTION_HEADER ;指针移动.endw;获取导入表 如果在前面获取导入表信息,那么就需要对内存地址和文件地址做转化比较麻烦;但是把数据拷贝到我们进程之后只需要访问内存进程就可以了mov esi, @pNTHdrassume esi:ptr IMAGE_NT_HEADERS;获取导入表地址 ,数组的第二个元素的第一个成员 mov eax, [esi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT*8].VirtualAddressadd eax, @dwImageBase ;获取导入表在进程的绝对地址 内存偏移 + 模块基址mov @pImpHdr, eax ;保存导入表的地址;处理导入表mov esi, @pImpHdrassume esi:ptr IMAGE_IMPORT_DESCRIPTOR.while TRUE ;遍历导入表;判断结束,全0项结束invoke crt_memcmp, esi, addr @hdrZeroImp.if eax == 0.break.endif;判断字段,为空则结束.if [esi].Name1 == NULL || [esi].FirstThunk == NULL.break.endif ;加载dllmov eax, [esi].Name1add eax, @dwImageBasepush ecxpush edxinvoke LoadLibrary, eax ;根据dll名加载 dll pop edxpop ecx;check 如果此时为空加说明无法找到dllmov @hDll, eax ;保存dll的模句柄;获取导入地址表,IATmov ebx, [esi].FirstThunkadd ebx, @dwImageBase;获取导入名称表,INTmov edi, ebx.if [esi].OriginalFirstThunk != NULLmov edi, [esi].OriginalFirstThunkadd edi, @dwImageBase .endif;遍历导入名称表.while dword ptr [edi] != 0.if dword ptr [edi] & 80000000h ;判断最高位是否为1;序号导入,获取序号mov edx, dword ptr [edi]and edx, 0ffffh ;获取低 word .else;名称导入mov edx, dword ptr [edi]add edx, @dwImageBaseadd edx, 2 ;名称前面有2个无用字节.endif;获取dll导入函数进程加载后地址push ecxpush edxinvoke GetProcAddress, @hDll, edxpop edxpop ecx;check;把地址存入 INT 表mov dword ptr [ebx], eaxadd ebx, 4add edi, 4.endwadd esi, size IMAGE_IMPORT_DESCRIPTOR.endw;清理invoke UnmapViewOfFile,@pPEBufinvoke CloseHandle,@hFileMapinvoke CloseHandle,@hFile; 执行加载的pe的代码jmp @dwOepretLoadPe endpstart:invoke LoadPeinvoke ExitProcess,0end start
需要合并节
.text,ERW

C++版:
#include <windows.h>
#include <concrt.h>
#include <iostream>
using namespace std;#define IMAGE_SIZE 0x5000//留空的全局变量
char szBuff[IMAGE_SIZE] = { 1 };#if 1
char g_szExeName[] = "PE.exe"; //需要加载的PE路径LPVOID lpMapAddr = NULL;HANDLE LoadPe()
{DWORD dwOldProc = 0;PIMAGE_IMPORT_DESCRIPTOR pImpHdr = NULL;IMAGE_IMPORT_DESCRIPTOR zeroImp = { 0 };HANDLE hDll = NULL;PIMAGE_THUNK_DATA pTmpThunk = NULL;DWORD dwPFNAddr = 0;DWORD dwIAT = 0;// 获取模块句柄HANDLE hInst = GetModuleHandle(NULL);// 读取文件HANDLE hFile = CreateFile(g_szExeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE){return 0;}// 创建文件映射对象HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);if (hFileMap == NULL){CloseHandle(hFile);return 0;}void* lpMapAddr = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);if (lpMapAddr == NULL){CloseHandle(hFileMap);CloseHandle(hFile);return 0;}// 拷贝PE头PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpMapAddr;PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)lpMapAddr + pDosHeader->e_lfanew);DWORD dwSizeOfHeaders = pNtHeader->OptionalHeader.SizeOfHeaders;DWORD dwNumOfSection = pNtHeader->FileHeader.NumberOfSections;//获取节表首地址 (选项头地址+ 大小)PIMAGE_SECTION_HEADER pSecHdr = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeader->FileHeader.SizeOfOptionalHeader + (DWORD)(&pNtHeader->OptionalHeader));DWORD dwOep = (DWORD)hInst + pNtHeader->OptionalHeader.AddressOfEntryPoint;// 更改内存属性VirtualProtect(hInst, IMAGE_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProc);//拷贝PE头memcpy(hInst, lpMapAddr, dwSizeOfHeaders);// 拷贝拷贝节区数据DWORD i = 0;while (dwNumOfSection > i){//拷贝数据DWORD pDst = (DWORD)hInst + (DWORD)pSecHdr->VirtualAddress;DWORD pSrc = (DWORD)lpMapAddr + (DWORD)pSecHdr->PointerToRawData;//DWORD pSrc = (DWORD)pSecHdr;memcpy((void*)pDst, (void*)pSrc, pSecHdr->SizeOfRawData);int nSecHdrSzie = sizeof(IMAGE_SECTION_HEADER);pSecHdr = (PIMAGE_SECTION_HEADER)((DWORD)pSecHdr + (DWORD)nSecHdrSzie);i++;}//获取导入表地址pImpHdr = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress + (DWORD)hInst);// 处理导入表while (TRUE){// 遇到全0项,遍历结束 int nRet = memcmp(pImpHdr, &zeroImp, sizeof(IMAGE_IMPORT_DESCRIPTOR));if (nRet == 0){break;}//判断字段, 为空则结束if (pImpHdr->Name == NULL || pImpHdr->FirstThunk == NULL){break;}DWORD pNameAddre = (DWORD)pImpHdr->Name + (DWORD)hInst;// 加载dllHMODULE hDll = LoadLibrary((LPCSTR)pNameAddre);if (hDll == NULL){break;}DWORD pFunAddr = 0;DWORD pIAT = (DWORD)pImpHdr->FirstThunk + (DWORD)hInst;DWORD pINT = (DWORD)pImpHdr->OriginalFirstThunk;if (pINT != 0){pFunAddr = pINT + (DWORD)hInst;}else{pFunAddr = pIAT;}// 遍历导入名称表while (true){DWORD pAddr = *(DWORD*)pFunAddr;if (pAddr == 0){break;}DWORD pFun = 0;if (pAddr & 0x80000000){//序号导入, 获取序号pFun = pAddr & 0xffff;}else{pFun = pAddr + 2 + (DWORD)hInst;}DWORD dwPFNAddr = (DWORD)GetProcAddress(hDll, (LPCSTR)LOWORD(pFun));*(DWORD*)pIAT = dwPFNAddr;pIAT += 4;pFunAddr+=4;}pImpHdr = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImpHdr + (DWORD)sizeof(IMAGE_IMPORT_DESCRIPTOR));}// 关闭句柄UnmapViewOfFile(lpMapAddr);CloseHandle(hFileMap);CloseHandle(hFile);// 返回地址return &dwOep;
}#endif // 0int main()
{#if 1// 加载PE文件,返回原OEPvoid* pOep = LoadPe();if (pOep != NULL){__asm jmp pOep}#endif // 0return 0;
}
#include <iostream>
#include <Windows.h>
#include <stdio.h>using namespace std;#define FILESIZE 0x00020000 //目标进程的SizeofImage
#define IMAGEBASE 0x01000000char szExeDataBuff[FILESIZE] = {1};
char g_szExeName[] = "winmine.exe"; //要加载的进程路径DWORD g_oep = 0;void LoadPe()
{// 创建文件映射//打开文件HANDLE hFile = CreateFile(g_szExeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE){return ;}// 创建文件映射对象HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);if (hFileMap == NULL){CloseHandle(hFile);return;}//将文件映射进内存LPVOID pView = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);if (pView == NULL){CloseHandle(hFileMap);CloseHandle(hFile);return;}// 修改代码节属性DWORD nOldProtect = 0;VirtualProtect((LPVOID)IMAGEBASE, FILESIZE, PAGE_EXECUTE_READWRITE, &nOldProtect);// 处理PEPIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pView;// 获取pe头大小PIMAGE_NT_HEADERS32 pNt = (PIMAGE_NT_HEADERS32)((DWORD)pView + pDos->e_lfanew);memcpy((void*)IMAGEBASE, (void*)pDos, pNt->OptionalHeader.SizeOfHeaders);// OEPg_oep = pNt->OptionalHeader.AddressOfEntryPoint + IMAGEBASE;// 解析节PIMAGE_SECTION_HEADER pSec = (PIMAGE_SECTION_HEADER)((DWORD) & (pNt->OptionalHeader.Magic) + pNt->FileHeader.SizeOfOptionalHeader);// 节数量unsigned int nNumberOfSections = pNt->FileHeader.NumberOfSections;while (nNumberOfSections != 0){void* pVirtualAddress = (void*)(pSec->VirtualAddress + IMAGEBASE);void* pFileAddress = (void*)(pSec->PointerToRawData + (DWORD)pDos);memcpy(pVirtualAddress, pFileAddress, pSec->SizeOfRawData);nNumberOfSections--;pSec++;}if (pNt->OptionalHeader.NumberOfRvaAndSizes > 2){// 处理导入表PIMAGE_IMPORT_DESCRIPTOR pIm = (PIMAGE_IMPORT_DESCRIPTOR)(pNt->OptionalHeader.DataDirectory[1].VirtualAddress + IMAGEBASE);while (pIm->Name && pIm->FirstThunk){HMODULE hModule = LoadLibraryA((char*)(pIm->Name + IMAGEBASE));if (hModule == NULL){pIm++;continue;}DWORD dwThunkData = pIm->OriginalFirstThunk ? pIm->OriginalFirstThunk : pIm->FirstThunk;if (dwThunkData == 0){return ;}PIMAGE_THUNK_DATA pThunkData = (PIMAGE_THUNK_DATA)(dwThunkData + IMAGEBASE);DWORD* pPfn = (DWORD*)(pIm->FirstThunk + IMAGEBASE);while (pThunkData->u1.AddressOfData){FARPROC farProc = 0;LPCSTR lpParam2 = 0;// 最高位判断if (pThunkData->u1.AddressOfData & 0x80000000){// 序号lpParam2 = LPCSTR(LOWORD(pThunkData->u1.AddressOfData));}else{// 函数名lpParam2 = LPCSTR(pThunkData->u1.AddressOfData + IMAGEBASE + 2);}farProc = GetProcAddress(hModule, lpParam2);// 填充IAT*pPfn = (DWORD)farProc;pThunkData++;pPfn++;}pIm++;}}//取消映射UnmapViewOfFile(pView);//关闭文件映射对象CloseHandle(hFileMap);//关闭文件CloseHandle(hFile);
}int main()
{LoadPe();if (g_oep != 0){__asm{jmp g_oep;}}return 0;
}
思路: 主要难点是代码后移,留出空间
方法1: 内联 汇编 开始 nop
方法2: 把代码放到dll中
方法3: 合并节,全局变量是放在未初始化的节内合并后就会在第一个节
合并节代码:
#include <Windows.h>
#pragma bss_seg (".mySec")
char g_aryImageSize[0x200000];#pragma bss_seg()
#pragma comment(linker,"/MERGE:.mySec=.textbss")const char* g_szExe = "mspaint.exe";int main()
{HANDLE hFile = NULL;HANDLE hFileMap = NULL;LPVOID pFileBuf = NULL;IMAGE_DOS_HEADER* pDosHdr = NULL;IMAGE_NT_HEADERS* pNtHdr = NULL;IMAGE_FILE_HEADER* pFileHdr = NULL;IMAGE_OPTIONAL_HEADER* pOptHdr = NULL;IMAGE_SECTION_HEADER* pSecHdr = NULL;IMAGE_IMPORT_DESCRIPTOR* pImpDes = NULL;DWORD dwSizeOfOptHdr = 0;DWORD dwNumOfSecs = 0;HANDLE hMod = NULL;DWORD dwSizeOfHeader = 0;DWORD dwOldProc = 0;DWORD dwEntry = 0;HMODULE hDll = NULL;LPDWORD pINT = NULL;LPDWORD pIAT = NULL;DWORD dwAddrOfFunc = 0;IMAGE_IMPORT_DESCRIPTOR zeroImp;memset(&zeroImp, 0, sizeof(IMAGE_IMPORT_DESCRIPTOR));//1、创建文件hMod = GetModuleHandle(NULL);hFile = CreateFile(g_szExe,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (hFile == INVALID_HANDLE_VALUE){OutputDebugString("Could not open file.");return -1;}//2、创建文件映射hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);if (hFileMap == NULL){OutputDebugString("Could not create file-mapping object.");return -1;}//3、映射文件内容到内存pFileBuf = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);if (pFileBuf == NULL){OutputDebugString("Could not map view of file.");return -1;}//4、解析DOS头pDosHdr = (IMAGE_DOS_HEADER*)pFileBuf;//5、解析NT头pNtHdr = (IMAGE_NT_HEADERS*)(pDosHdr->e_lfanew + (char*)pFileBuf);//6、解析文件头pFileHdr = &(pNtHdr->FileHeader);//7、解析选项头pOptHdr = &(pNtHdr->OptionalHeader);//8、获取节表个数和选项头大小dwSizeOfOptHdr = pFileHdr->SizeOfOptionalHeader;dwNumOfSecs = pFileHdr->NumberOfSections;//9、解析节表pSecHdr = (IMAGE_SECTION_HEADER*)((char*)pOptHdr + dwSizeOfOptHdr);//10、获取PE头大小和入口点(RVA)dwSizeOfHeader = pOptHdr->SizeOfHeaders;dwEntry = pOptHdr->AddressOfEntryPoint + (DWORD)hMod;//11、获取导入表入口pImpDes = (IMAGE_IMPORT_DESCRIPTOR*)pOptHdr->DataDirectory[1].VirtualAddress;pImpDes = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD)pImpDes + (DWORD)hMod);//12、拷贝PE头VirtualProtect(hMod, dwSizeOfHeader, PAGE_EXECUTE_READWRITE, &dwOldProc);memcpy(hMod, pDosHdr, dwSizeOfHeader);//13、拷贝节数据IMAGE_SECTION_HEADER* pSecTmpHdr = pSecHdr;for (size_t i = 0; i < dwNumOfSecs; i++){LPVOID pSecDataFileOffset = (char*)pFileBuf + pSecTmpHdr->PointerToRawData;LPVOID pSecDataMemory = (LPVOID)((DWORD)hMod + pSecTmpHdr->VirtualAddress);VirtualProtect(pSecDataMemory, pSecTmpHdr->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &dwOldProc);memcpy(pSecDataMemory, pSecDataFileOffset, pSecTmpHdr->SizeOfRawData);pSecTmpHdr = (IMAGE_SECTION_HEADER*)((char*)pSecTmpHdr + sizeof(IMAGE_SECTION_HEADER));}//14、拷贝导入表信息while (true){if (pImpDes->Characteristics == 0 &&pImpDes->FirstThunk == 0 &&pImpDes->Name == 0){break;}if (pImpDes->Name == NULL){break;}LPSTR pDllName = (LPSTR)((DWORD)hMod + pImpDes->Name);hDll = LoadLibrary(pDllName);if (pImpDes->FirstThunk == NULL){break;}//获取导入名称表pINT = (LPDWORD)((DWORD)hMod + pImpDes->OriginalFirstThunk);if (pINT == NULL){pINT = (LPDWORD)((DWORD)hMod + pImpDes->FirstThunk);}//获取导入地址表pIAT = (LPDWORD)((DWORD)hMod + pImpDes->FirstThunk);//while (true){DWORD dwINT = *pINT;if (dwINT == 0){break;}//判断是符号导入还是名称导入LPSTR pApiName = NULL;if (dwINT & 0x80000000){pApiName = (LPSTR)dwINT;pApiName = LPSTR((DWORD)pApiName & 0x0000ffff);}else{pApiName = LPSTR(dwINT + (DWORD)hMod + sizeof(WORD));}*pIAT = (DWORD)GetProcAddress(hDll, pApiName);pINT++;pIAT++;}pImpDes++;}__asm jmp dwEntry;return 0;
}相关文章:
WindowsPE文件格式入门05.PE加载器LoadPE
https://bpsend.net/thread-316-1-1.html LoadPE - pe 加载器 壳的前身 如果想访问一个程序运行起来的内存,一种方法就是跨进程读写内存,但是跨进程读写内存需要来回调用api,不如直接访问地址来得方便,那么如果我们需要直接访问地址,该怎么做呢?.需要把dll注进程,注进去的代码…...
使用Cusor 生成 Figma UI 设计稿
一、开发环境 系统:MacOS 软件版本: Figma(网页或APP版) 注:最好是app版,网页版figma 没有选项 import from manifest app下载地址:Figma Downloads | Web Design App for Desktops & …...
Golang的文件同步与备份
Golang的文件同步与备份 一、Golang介绍 也称为Go语言,是谷歌开发的一种编程语言,具有高效的并发编程能力和出色的内存管理。由于其快速的编译速度和强大的标准库,Golang在网络应用、云平台和大数据等领域得到了广泛应用。 二、文件同步与备份…...
如何用人工智能大模型,进行作业批改?
今天我们学习人工智能大模型如何进行作业批改。手把手学习视频请访问https://edu.csdn.net/learn/40402/666452 第一步,进入讯飞星火。打开google浏览器,输入百度地址后,搜索”讯飞星火”,在搜索的结果中,点第一个讯飞…...
MATLAB之数据分析图系列 三
三维堆叠柱状图 Bar3StackPlot.m文件 clc; clear; close all; %三维堆叠柱状图 %% 数据准备 % 读取数据 load data.mat % 初始化 dataset X; s 0.4; % 柱子宽度 n size(dataset,3); % 堆叠组数%% 图片尺寸设置(单位:厘米) figureUnits c…...
python爬虫:DrissionPage实战教程
如果本文章看不懂可以看看上一篇文章,加强自己的基础:爬虫自动化工具:DrissionPage-CSDN博客 案例解析: 前提:我们以ChromiumPage为主,写代码工具使用Pycharm(python环境3.9-3.10) …...
一、STM32简介
一、实验器材介绍 二、STM32简介 1.STM32 名词解释 STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ST,指ST公司(意法半导体);M,MicroController 微控制器(MCU,MicroController Unit 微控制器单元/单片机&…...
[ctfshow web入门] web2
前置知识 js是可以写在网页中,用于控制网页行为,例如现在表现出无法使用F12,常见用法校验前台登录时输入的邮箱格式是否正确 view-source协议是一种早期就存在的协议,基本上所有主流浏览器都支持这一协议,因此用户…...
torch 拆分子张量 分割张量
目录 unbind拆分子张量 1. 沿着第n个维度拆分(即按“批次”拆分) split分割张量 常用用法: 总结: unbind拆分子张量 import torchquaternions torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]) result torch.unbind(quaternio…...
定制一款国密浏览器(2):修改包名
在上一章中,介绍了 chromium 源码的获取和构建deb 包,这一章将修改包名。 我给定制浏览器取名 Mojo Browser,Mojo 这个词来自 Chromium 代码中的 Mojo 跨进程框架,此外 Mojo 隐含有突破困境的内在动力的意思。 所以接下修改包名为 org.mojo.browser,第二就是修改程序的安…...
使用MATIO库读取Matlab数据文件中的多维数组
使用MATIO库读取Matlab数据文件中的多维数组 MATIO是一个用于读写Matlab数据文件(.mat)的开源C库。下面是一个完整的示例程序,展示如何使用MATIO库读取Matlab数据文件中的多维数组。 示例程序 #include <stdio.h> #include <stdlib.h> #include <…...
MySQL篇(五)MySQL主从同步原理深度剖析
MySQL篇(五)MySQL主从同步原理深度剖析 MySQL篇(五)MySQL主从同步原理深度剖析一、引言二、MySQL主从同步基础概念主库(Master)从库(Slave)二进制日志(Binary Log&#x…...
PyQt5和OpenCV车牌识别系统
有需要请加文章底部Q哦 可远程调试 PyQt5和OpenCV车牌识别系统 一 介绍 此车牌识别系统基于PyQt5和OpenCV开发,蓝牌,新能源(绿牌),黄牌,白牌均可以准确识别,支持中文识别,可以导出识别结果(Excel格式)。此…...
【Android Studio 下载 Gradle 失败】
路虽远行则将至,事虽难做则必成 一、事故现场 下载Gradle下载不下来,没有Gradle就无法把项目编译为Android应用。 二、问题分析 观察发现下载时长三分钟,进度条半天没动,说明这个是国外的东西,被墙住了,需…...
Xshell Plus 6下载与安装
文章目录 Xshell Plus 6 简介(一)网络连接与协议支持(二)会话管理(三)安全特性(四)文件传输功能(因集成Xftp 6 )(五)个性化与便捷功能…...
格式工厂怎样插入内置音频文件
打开格式工厂,在打开的页面选择 “视频” 选项;在视频选项里点击 “混流”;在混流页面右侧点击 “添加文件”,分别添加上视频文件和要插入的内置音频文件;在 “输出设置” 的下拉菜单里,分别选好要输出的视…...
CNN 里面能自然起到防止过拟合的办法
在 CNN(卷积神经网络)中,其实有 一些结构和机制 天然就具有防止过拟合(overfitting)的作用,不完全依赖额外的正则化手段。 🧠 一、CNN 天然防过拟合的几个原因: 1️⃣ 局部连接&…...
九、重学C++—类和函数
上一章节: 八、重学C—动态多态(运行期)-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/147004745?spm1001.2014.3001.5502 本章节代码: cpp/cppClassAndFunc.cpp CuiQingCheng/cppstudy - 码云 - 开源中国…...
使用MCP服务器实现AI任务完成通知:让Cursor更智能
0. 简介 在使用AI工具进行长时间任务时,常常需要等待结果。MCP(Model Context Protocol)服务器"mcp_server_notify"提供了一个优雅的解决方案,让AI在完成任务后通过系统通知提醒你。本文将介绍如何在Cursor中配置和使用…...
解决 Hugging Face SentenceTransformer 下载失败的完整指南:ProxyError、SSLError与手动下载方案
问题背景 在使用 Hugging Face 的 SentenceTransformer 加载预训练模型 all-MiniLM-L6-v2 时,遇到了以下错误: 代理连接失败(ProxyError / SSLError: KRB5_S_TKT_NYV)大文件下载中断(unexpected EOF while reading&a…...
Linux | I.MX6ULL开发板固件烧录所需文件详述(9)
01 搞清楚手里的开发板是 EMMC 还是 NAND FLASH 。默认我的商业级是EMMC ,开关:10011010 终结者i.MX6ULL 开卡板分为工业级和商业级两种不同的开发板。 商业级的核心板,它的存储是 EMMC 的,EMMC 的存储是类似于正方形的芯片,旁边是 NAND FLASH的一个封装,因为我们这里…...
论文阅读笔记:Denoising Diffusion Implicit Models (5)
0、快速访问 论文阅读笔记:Denoising Diffusion Implicit Models (1) 论文阅读笔记:Denoising Diffusion Implicit Models (2) 论文阅读笔记:Denoising Diffusion Implicit Models (…...
【AI论文】GPT-ImgEval:一个用于诊断GPT4o在图像生成方面的综合基准
摘要:OpenAI的GPT4o模型最近的突破在图像生成和编辑方面展现了令人惊讶的良好能力,引起了社区的极大兴奋。 本技术报告介绍了第一眼评估基准(名为GPT-ImgEval),定量和定性诊断GPT-4o在三个关键维度的性能:&…...
CSS3学习教程,从入门到精通, 学院网站完整项目 - HTML5 + CSS3 实现(25)
学院网站完整项目 - HTML5 CSS3 实现 下面是一个完整的学院网站项目,包含主页、新闻列表页、新闻详情页和视频宣传页的实现。我将按照您的要求提供详细的代码和注释。 项目结构 college-website/ ├── index.html # 主页 ├── news-list.html …...
Java虚拟机面试题:内存管理(中)
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
如何绕过myabtis-plus的逻辑删除条件
目标 mp中所有方法都会带上逻辑删除,如果启用了逻辑删除,有时候我们需要忽略逻辑删除.改如何实现 解决方法 自定义DeleteReal 方法 import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.ba…...
王者荣耀的游戏匹配机制
王者荣耀的匹配机制主要基于ELO评分系统(隐藏分机制)和段位匹配,旨在平衡对局双方实力,同时通过多种策略控制玩家胜率趋近50%。 一、匹配机制核心 1. ELO评分(隐藏分) - 系统根据玩家的胜负、KDA、伤害量、…...
游戏无法启动?XINPUT1_3.dll 丢失的终极解决方案
当你兴奋地启动一款新游戏时,突然弹出一个错误提示——‘程序无法启动,因为计算机中丢失 XINPUT1_3.dll’。这种问题在 PC 玩家中非常常见,尤其是运行一些较老的游戏时。XINPUT1_3.dll 是 DirectX 运行库的关键组件,缺失会导致游戏…...
macOS下SourceInsight的替代品
macOS 推荐的几款开源、轻量级、且功能类似于 SourceInsight 的源码阅读工具(排除 VS Code): 1. Zeal(离线文档 简单代码导航) 官网/GitHub: https://zealdocs.org/特点: 轻量级离线文档浏览器࿰…...
嵌入式硬件如何在PADS中将原理图转换为PCB详解
本文旨在讲述如何在PADS中将原理图转换为PCB。 本文以C51原理图作为例子。 1.首先在桌面上打开PADS Logic 2.找到菜单栏的文件选项,然后点击新建。 点击新建之后出现如下界面。...
