能力值:
( LV2,RANK:10 )
|
-
-
2 楼
具体代码如下:
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <SYS\STAT.H>
#include <poppack.h>
#include <pshpack1.h>
#include <iostream.h>
int alig(int size,unsigned int align)
{
if(size%align!=0)
return (size/align+1)*align;
else
return size;
}
int map_exe(const void *base)
{
IMAGE_DOS_HEADER * dos_head;
dos_head =(IMAGE_DOS_HEADER *)base;
typedef struct PE_HEADER_MAP
{
DWORD signature;
IMAGE_FILE_HEADER _head;
IMAGE_OPTIONAL_HEADER opt_head;
IMAGE_SECTION_HEADER section_header[8];
} peHeader;
if (dos_head->e_magic != IMAGE_DOS_SIGNATURE)
{
puts("unknown type of file");
return 0;
}
else printf("IS type of filen\n");
peHeader * header;
header = (peHeader *)((char *)dos_head + dos_head->e_lfanew);//得到PE文件头
if (IsBadReadPtr(header, sizeof(*header)))
{
puts("(no PE header, probably DOS executable)\n");
return 0;
}
else
{puts("( PE header, NO probably DOS executable)");
cout<< IMAGE_DOS_SIGNATURE ;
return 1;
}
}
PIMAGE_NT_HEADERS GetNtHeaders(LPVOID ImageBase)
{
if(!map_exe(ImageBase))
return NULL;
PIMAGE_NT_HEADERS pNtH;
PIMAGE_DOS_HEADER pDH;
pDH=(PIMAGE_DOS_HEADER)ImageBase;
pNtH=(PIMAGE_NT_HEADERS)((DWORD)pDH+pDH->e_lfanew);
return pNtH;
}
//
PIMAGE_FILE_HEADER GetFileHeader(LPVOID ImageBase)
{
PIMAGE_DOS_HEADER pDH=NULL;
PIMAGE_NT_HEADERS pNtH=NULL;
PIMAGE_FILE_HEADER pFH=NULL;
if(!map_exe(ImageBase))
return NULL;
pDH=(PIMAGE_DOS_HEADER)ImageBase;
pNtH=(PIMAGE_NT_HEADERS)((DWORD)pDH+pDH->e_lfanew);
pFH=&pNtH->FileHeader;
return pFH;
}
PIMAGE_OPTIONAL_HEADER GetOptionalHeader(LPVOID ImageBase)
{
PIMAGE_DOS_HEADER pDH=NULL;
PIMAGE_NT_HEADERS pNtH=NULL;
PIMAGE_OPTIONAL_HEADER pOH=NULL;
if(!map_exe(ImageBase))
return NULL;
pDH=(PIMAGE_DOS_HEADER)ImageBase;
pNtH=(PIMAGE_NT_HEADERS)((DWORD)pDH+pDH->e_lfanew);
pOH=&pNtH->OptionalHeader;
return pOH;
}
int main(int argc,char **argv)
{
HANDLE hFile, hMapping;
void *basepointer;
FILETIME * Createtime;
FILETIME * Accesstime;
FILETIME * Writetime;
Createtime = new FILETIME;
Accesstime = new FILETIME;
Writetime = new FILETIME;
PIMAGE_FILE_HEADER pFH=NULL;
PIMAGE_OPTIONAL_HEADER pOH=NULL;
PIMAGE_NT_HEADERS pNtH;
if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)//打开要修改的文件
{
puts("(could not open)");
return EXIT_FAILURE;
}
if(!GetFileTime(hFile,Createtime,Accesstime,Writetime))
{
printf("\nerror getfiletime: %d\n",GetLastError());
}
//得到要修改文件的创建、修改等时间
if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
{
puts("(mapping failed)");
CloseHandle(hFile);
return EXIT_FAILURE;
}
if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))
{
puts("(view failed)");
CloseHandle(hMapping);
CloseHandle(hFile);
return EXIT_FAILURE;
}
//把文件头映象存入baseointer
CloseHandle(hMapping);
CloseHandle(hFile);
map_exe(basepointer);//得到相关地址
char szNewFile[10]="_New.exe";
if(!CopyFile(argv[1],szNewFile,0)) //若备份文件出错则退出
{
printf("\t\tbak faild\n");
exit(-1);
}
IMAGE_NT_HEADERS NThea;
FILE* rwFile;
rwFile=fopen(argv[1],"rb");
fseek(rwFile,0x3c,0);
pFH= GetFileHeader(basepointer);
pOH=GetOptionalHeader(basepointer);
pNtH=GetNtHeaders(basepointer);
DWORD pNT; //pNT中存放IMAGE_NT_HEADERS结构的地址
fread(&pNT,sizeof(DWORD),1,rwFile);
fseek(rwFile,pNT,0);
fread(&NThea,sizeof(IMAGE_NT_HEADERS),1,rwFile); //读取原文件的IMAGE_NT_HEADERS结构
//保存原文件区块数量与OEP
int nOldSectionNo=pFH->NumberOfSections;
if(NThea.OptionalHeader.SizeOfCode==pOH->SizeOfCode)printf("\n121.llydd\n");
int OEP=pOH->AddressOfEntryPoint;
int SECTION_ALIG=pOH->SectionAlignment;
//保存文件对齐值与区块对齐值lignment;
int FILE_ALIG=pOH->FileAlignment;
//定义要添加的区块
IMAGE_SECTION_HEADER NewSection;
//将该结构全部清零
memset(&NewSection, 0, sizeof(IMAGE_SECTION_HEADER));
//再定义一个区块,来存放原文件最后一个区块的信息
IMAGE_SECTION_HEADER SEChea;
//读原文件最后一个区块的信息
fseek(rwFile,pNT+248,0);
for(int i=0;i<nOldSectionNo;i++)
fread(&SEChea,sizeof(IMAGE_SECTION_HEADER),1,rwFile);
FILE *newfile=fopen(szNewFile,"rb+");
if(newfile==NULL)
{
printf("\t\tOpen bak file faild\n");
exit(-1);
}
fseek(newfile,SEChea.PointerToRawData+SEChea.SizeOfRawData,SEEK_SET);
goto shellend;
__asm
{
shell: PUSHAD
MOV EAX,DWORD PTR FS:[30H] ;FS:[30H]指向PEB
MOV EAX,DWORD PTR [EAX+0CH] ;获取PEB_LDR_DATA结构的指针
MOV EAX,DWORD PTR [EAX+1CH] ;获取LDR_MODULE链表表首结点的inInitializeOrderModuleList成员的指针
MOV EAX,DWORD PTR [EAX] ;LDR_MODULE链表第二个结点的inInitializeOrderModuleList成员的指针
MOV EAX,DWORD PTR [EAX+08H] ;inInitializeOrderModuleList偏移8h便得到Kernel32.dll的模块基址
MOV EBP,EAX ; 将Kernel32.dll模块基址地址放至kernel中
MOV EAX,DWORD PTR [EAX+3CH] ;指向IMAGE_NT_HEADERS
MOV EAX,DWORD PTR [EBP+EAX+120] ;指向导出表
MOV ECX,[EBP+EAX+24] ;取导出表中导出函数名字的数目
MOV EBX,[EBP+EAX+32] ;取导出表中名字表的地址
ADD EBX,EBP
PUSH WORD PTR 0X00 ;构造GetProcAddress字符串
PUSH DWORD PTR 0X73736572
PUSH DWORD PTR 0X64644163
PUSH DWORD PTR 0X6F725074
PUSH WORD PTR 0X6547
MOV EDX,ESP
PUSH ECX
F1:
MOV EDI,EDX
POP ECX
DEC ECX
TEST ECX,ECX
JZ EXIT
MOV ESI,[EBX+ECX*4]
ADD ESI,EBP
PUSH ECX
MOV ECX,15
REPZ CMPSB
TEST ECX,ECX
JNZ F1
POP ECX
MOV ESI,[EBP+EAX+36] ;取得导出表中序号表的地址
ADD ESI,EBP
MOVZX ESI,WORD PTR[ESI+ECX*2] ;取得进入函数地址表的序号
MOV EDI,[EBP+EAX+28] ;取得函数地址表的地址
ADD EDI,EBP
MOV EDI,[EDI+ESI*4] ;取得GetProcAddress函数的地址
ADD EDI,EBP
PUSH WORD PTR 0X00 ;构造LoadLibraryA字符串
PUSH DWORD PTR 0X41797261
PUSH DWORD PTR 0X7262694C
PUSH DWORD PTR 0X64616F4C
PUSH ESP
PUSH EBP
CALL EDI ;调用GetProcAddress取得LoadLibraryA函数的地址
PUSH WORD PTR 0X00 ;构造test符串,测试新增节后的EXE是否能正常加载test.dll
PUSH DWORD PTR 0X74736574
PUSH ESP
CALL EAX
EXIT: ADD ESP,36 ;平衡堆栈
POPAD
}
shellend:
char *pShell;
int nShellLen;
__asm
{
LEA EAX,shell
MOV pShell,EAX;
LEA EBX,shellend
SUB EBX,EAX
MOV nShellLen,EBX
}
//写入SHELLCODE,
for(i=0;i<nShellLen;i++)
fputc(pShell[i],newfile);
//SHELLCODE之后是跳转到原OEP的指令
NewSection.VirtualAddress=SEChea.VirtualAddress+alig(SEChea.Misc.VirtualSize,SECTION_ALIG);
BYTE jmp = 0xE9;
OEP=OEP-(NewSection.VirtualAddress+nShellLen)-5;
fwrite(&jmp, sizeof(jmp), 1, newfile);
fwrite(&OEP, sizeof(OEP), 1, newfile);
//将最后增加的数据用0填充至按文件中对齐的大小
for(i=0;i<alig(nShellLen,FILE_ALIG)-nShellLen-5;i++)
fputc('\0',newfile);
if(NThea.OptionalHeader.SizeOfCode==pOH->SizeOfCode)printf("\n121.llydd\n");
//新区块中的数据
strcpy((char*)NewSection.Name,".llydd");
NewSection.PointerToRawData=SEChea.PointerToRawData+SEChea.SizeOfRawData;
NewSection.Misc.VirtualSize=nShellLen;
NewSection.SizeOfRawData=alig(nShellLen,FILE_ALIG);
NewSection.Characteristics=0xE0000020;//新区块可读可写可执行
fseek(newfile,pNT+248+sizeof(IMAGE_SECTION_HEADER)*nOldSectionNo,0);
//写入新的块表
fwrite(&NewSection,sizeof(IMAGE_SECTION_HEADER),1,newfile);
if(NThea.OptionalHeader.SizeOfCode==pOH->SizeOfCode)printf("\n124.llydd\n");
int nNewImageSize=NThea.OptionalHeader.SizeOfImage+alig(nShellLen,SECTION_ALIG);
int nNewSizeofCode=NThea.OptionalHeader.SizeOfCode+alig(nShellLen,FILE_ALIG);
fseek(newfile,pNT,0);
if(NThea.OptionalHeader.SizeOfCode==pOH->SizeOfCode)printf("\n121.llydd\n");
NThea.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0;
NThea.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0;
if(NThea.OptionalHeader.SizeOfCode==pOH->SizeOfCode)printf("\n191.d\n");
pOH->SizeOfCode=nNewSizeofCode;
NThea.OptionalHeader.SizeOfImage=nNewImageSize;
if(NThea.OptionalHeader.SizeOfCode==pOH->SizeOfCode)printf("\n171.llydd\n");
NThea.FileHeader.NumberOfSections=nOldSectionNo+1;
NThea.OptionalHeader.AddressOfEntryPoint=NewSection.VirtualAddress;
//写入更新后的PE头结构
fwrite(&NThea,sizeof(IMAGE_NT_HEADERS),1,newfile);
printf("\t\tok.........!\n");
fclose(newfile);
fclose(rwFile);
return 1;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
在软件加密技术内幕中说 GetNtHeaders(LPVOID ImageBase)
GetOptionalHeader(LPVOID ImageBase)
GetFileHeader(LPVOID ImageBase)
这些函数能得到PE信息
与下面的方法得到的有什么不同啊?
IMAGE_NT_HEADERS NThea;
fseek(rwFile,0x3c,0);
DWORD pNT; //pNT中存放IMAGE_NT_HEADERS结构的地址
fread(&pNT,sizeof(DWORD),1,rwFile);
fseek(rwFile,pNT,0);
fread(&NThea,sizeof(IMAGE_NT_HEADERS),1,rwFile); //读取原文件的IMAGE_NT_HEADERS结构
得到的头信息是一样的吗?/??
|