-
-
[求助]增加PE文件节区+修改IID结构(静态干预输入表)---参考加密与解密第4版P450-P455
-
发表于: 2020-1-2 11:04 1738
-
恰巧看到了加密与解密第4版的静态干预输入表,便想着尝试代码实现一番,在具体实现中遇到了部分BUG,不知道在什么情况下,导致了很多程序修改完后无法启动(0xC0000005),而修改自己编写的一些程序,大部分都可以成功。
步骤:
1.PE文件添加区块
2.将原始输入表拷贝到新节区
3.加入新的IID结构
4.使用原始输入表位置来存放新的IID内容
5.修复镜像大小以及输入表RVA
#include<stdio.h> #include<windows.h> void infecting(char *);//修改导入表 LPVOID rva2raw(PIMAGE_SECTION_HEADER,DWORD,WORD);//RVA转RAW char dllname[]="mydll.dll";//要加入的DLL名称 char path[MAX_PATH] = "c:\\Users\\Admin\\Desktop\\hello.exe";//要修改的文件名称 void main() { infecting(path); } void infecting(char * path) { HANDLE hFile; HANDLE hFileMap; LPVOID mapView; hFile = CreateFileA(path,GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//打开文件句柄 if(hFile == INVALID_HANDLE_VALUE) return; hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,0x1000,NULL);//创建文件映射对象 if(hFileMap == NULL) return; mapView = (PCHAR)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,NULL, NULL, NULL);//将文件映射到该进程 if(mapView == NULL) return; PIMAGE_DOS_HEADER pDos = PIMAGE_DOS_HEADER(mapView);//指向dos头 PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pDos->e_lfanew+(DWORD)pDos);//指向NT头 PIMAGE_FILE_HEADER pFile = PIMAGE_FILE_HEADER((BYTE *)pNt+4);//指向FILE头 PIMAGE_OPTIONAL_HEADER pOpt = PIMAGE_OPTIONAL_HEADER(&pNt->OptionalHeader);//指向OPTIONAL头 PIMAGE_SECTION_HEADER pSect = IMAGE_FIRST_SECTION(pNt);//指向section头 //判断是否PE文件 if(pDos->e_magic == 0x5A4D&&pNt->Signature == 0x4550) { //判断是否32为PE if(pOpt->Magic == 0x010B) { //判断是否有签名 if(!pOpt->DataDirectory[4].VirtualAddress||!pOpt->DataDirectory[4].Size) { //零填充绑定输入 if( pOpt->DataDirectory[11].VirtualAddress)//判断绑定输入是否为空 { pOpt->DataDirectory[11].VirtualAddress = 0; pOpt->DataDirectory[11].Size =0; //0填充 } //区块名,判断是否被感染 if(strcmp((PCHAR)((pSect+pFile->NumberOfSections-1)->Name),".hacked")) { //添加节区 PIMAGE_SECTION_HEADER pSectHack = &pSect[pFile->NumberOfSections]; memcpy(pSectHack->Name,".hacked",8); //计算VA DWORD vasize; if(((pSect+pFile->NumberOfSections-1)->Misc.VirtualSize)%(pOpt->SectionAlignment)) vasize = ((pSect+pFile->NumberOfSections-1)->Misc.VirtualSize)/(pOpt->SectionAlignment)+1; else vasize = ((pSect+pFile->NumberOfSections-1)->Misc.VirtualSize)/(pOpt->SectionAlignment); pSectHack->Misc.VirtualSize = vasize*(pOpt->SectionAlignment);//新节块的Virtualsize pSectHack->VirtualAddress = (pSect+pFile->NumberOfSections-1)->VirtualAddress+vasize*(pOpt->SectionAlignment); //计算新的rawsize DWORD rawsize; if((pOpt->DataDirectory[1].Size+0x14)%(pOpt->FileAlignment)) rawsize = (pOpt->DataDirectory[1].Size+0x14)/(pOpt->FileAlignment)+1; else rawsize = (pOpt->DataDirectory[1].Size+0x14)/(pOpt->FileAlignment);//因为要加新的IID,所以加14 pSectHack->SizeOfRawData = rawsize*(pOpt->FileAlignment);//新节块的rawsize pSectHack->PointerToRawData = (pSect+pFile->NumberOfSections-1)->PointerToRawData+(pSect+pFile->NumberOfSections-1)->SizeOfRawData;//计算区块偏移 pSectHack->Characteristics = 0xC0000040;//可写对齐 pSectHack->NumberOfRelocations = 0;//无需重定向 pSectHack->NumberOfLinenumbers = 0; pSectHack->PointerToLinenumbers = 0; pSectHack->PointerToRelocations = 0; //干预输入表,备份输入表到新的节区,加入新IID LPCVOID buf = new BYTE[pSectHack->SizeOfRawData];//申请内存存放新IID结构 PDWORD resize = new DWORD[1];//存储实际读入字节 memset((PVOID)buf,0,pSectHack->SizeOfRawData);//内存初始化为0 LONG IIDraw = (LONG)rva2raw(pSect,pOpt->DataDirectory[1].VirtualAddress,pFile->NumberOfSections);//原始IID的raw SetFilePointer(hFile,IIDraw,NULL,FILE_BEGIN);//文件指针指向IID数组 ReadFile(hFile,(PVOID)buf,pOpt->DataDirectory[1].Size,resize,NULL);//将原始IID读入到申请的内存 PIMAGE_IMPORT_DESCRIPTOR myIID = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)buf+pOpt->DataDirectory[1].Size-0x14);//将原IID数组最后一项空IID声明为IID结构 myIID->ForwarderChain=0;//无需转向 myIID->TimeDateStamp=0;//忽略时间戳 //找地址,写入新IID的各项内容,在这里我顺手反用了原始IID数组的地址 PVOID oldiid = new BYTE*[pOpt->DataDirectory[1].Size];//清空原始IID数组 memset(oldiid,0,pOpt->DataDirectory[1].Size); SetFilePointer(hFile,IIDraw,NULL,FILE_BEGIN); WriteFile(hFile,oldiid,pOpt->DataDirectory[1].Size,resize,NULL); //将原始IID数组改为新IID所需要的内容 myIID->OriginalFirstThunk=pOpt->DataDirectory[1].VirtualAddress;//INT,指向原始IID数组位置 LPVOID originalraw =rva2raw(pSect,pOpt->DataDirectory[1].VirtualAddress,pFile->NumberOfSections);//rva转raw,修改实际文件内容 SetFilePointer(hFile,(LONG)originalraw,NULL,FILE_BEGIN);//文件指针指向新IID的originalFirstThunk DWORD iat =(pOpt->DataDirectory[1].VirtualAddress+0x20);//找地址存放IAT/INT WriteFile(hFile,&iat,sizeof(DWORD),resize,NULL);//将新区块指向INT的RVA地址写入,既写入original的内容 //找地址,写入新IID的FirstTrunk myIID->FirstThunk=pOpt->DataDirectory[1].VirtualAddress+8;//,同样在原来IID数组找个位置填充IAT SetFilePointer(hFile,(LONG)originalraw+8,NULL,FILE_BEGIN);//文件指针指向新IID的FirstThunk WriteFile(hFile,&iat,sizeof(DWORD),resize,NULL);//将新区块指向INT的RVA地址写入,既写入Firsttrunk的内容 //找地址,写入新IID的name的ascii myIID->Name=pOpt->DataDirectory[1].VirtualAddress+0x10;//RVA,同样在原来IID数组找个位置填充name SetFilePointer(hFile,(LONG)originalraw+0x10,NULL,FILE_BEGIN);//文件指针指向新IID的name WriteFile(hFile,dllname,sizeof(dllname),resize,NULL);//将字符串name写入 //构建好IID结构内容与INA/IAT PVOID nop = new BYTE[2];//Hint,0填充 memset(nop,0,sizeof(BYTE)*2); char funname[]="msg"; SetFilePointer(hFile,(LONG)originalraw+0x20,NULL,FILE_BEGIN);//文件指针指向新IID的INT/IAT WriteFile(hFile,nop,sizeof(BYTE)*2,resize,NULL); WriteFile(hFile,funname,sizeof(funname),resize,NULL);//将IMAGE_IMPORT_BY_NAME写入 //写入新区块 SetFilePointer(hFile,pSectHack->PointerToRawData,NULL,FILE_BEGIN);//文件指针指向新区块开头 WriteFile(hFile,buf,pSectHack->SizeOfRawData,resize,NULL);//将新区块内容写入文件 pFile->NumberOfSections++;//节区数目加1 pOpt->SizeOfImage += vasize*(pOpt->SectionAlignment);//修正Image大小 //修改原始输入表信息 pOpt->DataDirectory[1].Size += 0x14; pOpt->DataDirectory[1].VirtualAddress = pSectHack->VirtualAddress; } } } } UnmapViewOfFile(mapView); CloseHandle(hFileMap); CloseHandle(hFile); } LPVOID rva2raw(PIMAGE_SECTION_HEADER pSect,DWORD rva,WORD num) { LPVOID offset=NULL; for(WORD i = 0;i<num;i++) { if(rva < (pSect->VirtualAddress+pSect->SizeOfRawData)&&rva > pSect->VirtualAddress)//遍历区块 { offset =(LPVOID) (rva-( (pSect->VirtualAddress)-(pSect->PointerToRawData) ));//计算文件偏移 return offset; } pSect++; } return offset; }
编写了一个简单的Dll,内容如下:
#include<stdio.h> #include<windows.h> BOOL WINAPI DllMain(HANDLE hmoudle,DWORD call,LPVOID lpreser) { switch(call) { case DLL_PROCESS_ATTACH: MessageBox(NULL,L"success!!!",L"注入成功",MB_OK); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return true; } extern "C"_declspec(dllexport)void msg() { MessageBox(NULL,L"success!!!",L"注入成功",MB_OK); }
新人发帖!如有问题请指出,及时更正。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-4-27 01:52
被yeanhoo编辑
,原因:
赞赏
看原图
赞赏
雪币:
留言: