首页
社区
课程
招聘
[求助]新手学习llydd的为PE文件增加新节,并在新节中增入SHELL CODE加载指定DLL一文的疑问
发表于: 2007-7-27 21:43 6138

[求助]新手学习llydd的为PE文件增加新节,并在新节中增入SHELL CODE加载指定DLL一文的疑问

2007-7-27 21:43
6138
部分代码:
IMAGE_NT_HEADERS NThea;
FILE* rwFile;
        rwFile=fopen(argv[1],"rb");
        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结构
pFH= GetFileHeader(basepointer);//读取原文IMAGE_FILE_HEADERS结构

        pOH=GetOptionalHeader(basepointer);//读取原文IMAGE_OPTIONAL_HEADERS结构

        pNtH=GetNtHeaders(basepointer);

        //写入新的块表

        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);
                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");//这个等式成立
        NThea.OptionalHeader.SizeOfCode=nNewSizeofCode; //但是把NThea.OptionalHeader.SizeOfCode用pOH->SizeOfCode替代会出现
Unhandled exception:0xC000005:Access Violation        ,不替代正确运行
           //写入更新后的PE头结构
        fwrite(&NThea,sizeof(IMAGE_NT_HEADERS),1,newfile);//用pNtH替代&NThea能正确运行但就不加载test.dll了这是为什么???

        printf("\t\tok.........!\n");

        fclose(newfile);
        fclose(rwFile);

        return 0;  
期待大哥们解答!!

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 234
活跃值: (10)
能力值: ( 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;
}
2007-7-27 22:06
0
雪    币: 234
活跃值: (10)
能力值: ( 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结构
           得到的头信息是一样的吗?/??
2007-7-27 22:33
0
游客
登录 | 注册 方可回帖
返回
//