zoukankan      html  css  js  c++  java
  • WIN PE文件插入MessageBox

     

     

    1.准备工作

    1.1获取MessageBox地址

    方法①:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdio.h>
    #include <windows.h>
     
    typedef void (*FuncPointer)(LPTSTR);  // 函数指针  
     
    int main()
    {   
        HINSTANCE LibHandle;
        FuncPointer GetAddr;
        // 加载成功后返回库模块的句柄 
        LibHandle = LoadLibrary("user32");  
        printf("user32 LibHandle = 0x%X\n", LibHandle);
        // 返回动态链接库(DLL)中的输出库函数地址
        GetAddr=(FuncPointer)GetProcAddress(LibHandle,"MessageBoxA");   
        printf("MessageBoxA = 0x%X\n", GetAddr);
        return 0;
    }

    方法②: 用OllyDBG加载notepad,左下角command框中输入bp MessageBoxA下断点。查看断点即可得MessageBox地址为:0x77D507EA

    1.2CALL和JMP的计算

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
    #include <windows.h>
    void func()
    {
        MessageBox(0, 0, 0, 0);
    }
    int main()
    {
        func();    
        return 0;
    }

    main函数反汇编:

    1
    2
    3
    4
    11:       func();
    0040D478 E8 8D 3B FF FF       call        @ILT+5(func) (0040100a)
    12:       return 0;
    0040D47D 33 C0                xor         eax,eax

    得到CALL的硬编码是E8
    call func继续跟进去:

    1
    2
    0040100A E9 01 00 00 00       jmp         func (00401010)
    0040100F CC                   int         3

    得到JMP的硬编码是E9
    func函数反汇编:

    1
    2
    3
    4
    5
    6
    7
    6:        MessageBox(0, 0, 0, 0);
    00401028 8B F4                mov         esi,esp
    0040102A 6A 00                push        0
    0040102C 6A 00                push        0
    0040102E 6A 00                push        0
    00401030 6A 00                push        0
    00401032 FF 15 AC A2 42 00    call        dword ptr [__imp__MessageBoxA@16 (0042a2ac)]

    观察到:

    1
    2
    3
      地址           机器指令              汇编指令                 指令所占字节数
    0040D478    E8 8D 3B FF FF   call @ILT+5(func)(0040100a)       5
    0040D47D

    E8后边的值并不是真正我们要调用的函数地址, 他们有以下关系:

    1
    2
    3
    4
    5
    E8这条指令的下一行地址    E8当前指令的地址    E8当前指令所占大小
         0x0040D47D     =     0x0040D478      +        0x5
     
    真正要跳转的地址      E8后边的值       E8当前指令的下一行地址
      0x0040100A    =    0xFFFF3B8D     +    0x0040D47D

    总结出:

    1
    2
    E8后边的值 = 真正要跳转的地址 - (E8当前指令的地址 + E8当前指令所占大小)
               = 真正要跳转的地址 - E8当前指令的下一行地址

    1.3构造shellcode

    通过之前的学习,可以构造出:

    1
    2
    3
    4
    5
    // 18 Bytes
    shellcode [] = {0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,  /* MessageBox4个参数入栈 */  
    0xE8, 0x00, 0x00, 0x00, 0x00, /* 调用MessageBox */
    0xE9, 0x00, 0x00, 0x00, 0x00  /* 跳到原程序的入口(AddressOfEntryPoint) */
    };

    2.代码区添加shellcode

    2.1分析PE结构

     

     

                                                                                     图1

     

     

                                                                                    图2  

    从图2中可以得到以下信息:

    1
    2
    3
    4
    5
    6
    IMAGE_OPTIONAL_HEADER(可选头)中部分成员信息:
    DWORD   AddressOfEntryPoint;  // 程序执行入口RVA      (0x0000739D)
    DWORD   ImageBase; // 程序的优先装载地址(基址)       (0x01000000)
    // 程序运行时,PE装载器先创建进程,再将文件载入内存,然后把EIP寄存器的值设置为:ImageBase + AddressOfEntryPoint;
    DWORD   SectionAlignment;  // 内存中节的对齐粒度       (0x00001000)
    DWORD   FileAlignment;  // 文件中节的对齐粒度          (0x00000200
    1
    2
    3
    4
    5
    IMAGE_SECTION_HEADER(节表第一项即代码区部分成员信息):
    DWORD   VirtualSize;  // 节区在内存中没有对齐前的实际大小 (0x00007748)
    DWORD   VirtualAddress;  // 节区在内存中起始位置(RVA)  (0x00001000)
    DWORD   SizeOfRawData;  // 节区在文件中对齐后的大小      (0x00007800) 
    DWORD   PointerToRawData;  // 节区在在文件中的偏移       (0x00000400)

    2.2判断空闲区域是否能放下shellcode

    计算文件中代码区空闲空间

    SizeOfRawData(0x7800) - VirtualSize(0x007748) >  0x12

    空闲空间大于shellcode长度,可以放得下。

    2.3将构造好的ShellCode写入空闲区:

    PointerToRawData(0x0400)+SizeOfRawData(0x7800)=0x7C00,

    在0x7B48与0x7C00之间写入shellcode:

     

     

                                                     图3

    2.4计算E8后边的值

    在计算相关值由文件映射到内存时,需要考虑内存对齐和文件对齐。

    真正要跳转的地址:MessageBox地址:0x77D507EA

    1
    2
    3
    4
    5
    文件中,E8下一行地址相对PointerToRawData偏移量:0x7B5D - 0x400 = 0x775D  
     
    映射到内存中,E8下一行地址:ImageBase + VirtualAddress + 0x775D = 0x0100875D 
     
    E8后边的值:MessageBox - 0x0100875D = 0x76D4808D

    2.5计算E9后边的值

    要保证MessageBox关闭后,程序能够正常运行,需要jmp到原来的OEP

    1
    2
    3
    4
    5
    6
    7
    原来OEP(真正要跳转的地址):ImageBase + AddressOfEntryPoint = 0x0100739D
     
    文件中,E9下一行地址相对PointerToRawData偏移量:0x7B62 - 0x400 = 7762  
     
    映射到内存中,E9下一行地址:ImageBase + VirtualAddress + 0x7762 = 0x01008762 
     
    E9后边的值:`0x0100739D - 0x01008762 = 0xFFFFEC3B`

    2.6修改OEP(AddressOfEntryPoint)

    1
    2
    3
    4
    5
    文件中shellcode起始地址相对PointerToRawData偏移量:0x7B50 - 0x400 = 0x7750  
     
    映射到内存中,相对ImageBase偏移:VirtualAddress + 0x7750 = 0x8750  
     
    将原来的OEP修改为,映射到内存后的shellcode起始地址(0x8750)。

    另存文件,双击,成功弹出MessageBox,如图4:

     



  • 相关阅读:
    apache安全—用户访问控制
    hdu 3232 Crossing Rivers 过河(数学期望)
    HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
    UVA 11020 Efficient Solutions (BST,Splay树)
    UVA 11922 Permutation Transformer (Splay树)
    HYSBZ 1208 宠物收养所 (Splay树)
    HYSBZ 1503 郁闷的出纳员 (Splay树)
    HDU 5416 CRB and Tree (技巧)
    HDU 5414 CRB and String (字符串,模拟)
    HDU 5410 CRB and His Birthday (01背包,完全背包,混合)
  • 原文地址:https://www.cnblogs.com/ganxiang/p/13173769.html
Copyright © 2011-2022 走看看