对于我们Lab2开发的shellcode,存在几个问题。

  1. 我们是写死了shellcode的起始地址,而程序每一次加载过程中,会出现栈帧移位现象,导致shellcode起始地址发生变化,导致shellcode失效
  2. 对于不同的机器,系统调用函数如MessageBoxA所在内存地址是不同,需要动态的查找其内存地址
  3. shellcode运行后,程序会直接崩溃,利用exit()函数终止程序

0x01 跳板技术jmp esp

我们注意到一个现象,在函数栈帧出栈后,ESP指向函数返回地址之后。所以可以将shellcode起始地址放在函数返回地址之后,返回位置覆盖为jmp esp指令的内存地址。因此我们还需要查找该指令内存地址,一个“万年不变”的内存地址是最好的。

查找跳转地址我们可以使用ollydbg插件ollyuni.dll,将其放在ollydbg安装plungins目录下即可使用,如图。不知道可不可以,在我电脑上运行直接卡死。
1.png

所以采用C++程序查找jmp esp这条指令存在地址,C程序如下。

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #define DLL_NAME "user32.dll"
  4. main()
  5. {
  6. BYTE* ptr;
  7. int position,address;
  8. HINSTANCE handle;
  9. BOOL done_flag = FALSE;
  10. handle=LoadLibrary(DLL_NAME); //加载动态链接库
  11. if(!handle)
  12. {
  13. printf(" load dll erro !");
  14. exit(0);
  15. }
  16. ptr = (BYTE*)handle; //ptr指向动态链接库基址
  17. for(position = 0; !done_flag; position++) //根据偏移查找指令
  18. {
  19. try
  20. {
  21. // 以后查找其他其他指令修改以下字段值即可
  22. if(ptr[position] == 0xFF && ptr[position+1] == 0xE4)
  23. {
  24. //0xFFE4 is the opcode of jmp esp
  25. int address = (int)ptr + position;
  26. printf("OPCODE found at 0x%x\n",address);
  27. }
  28. }
  29. catch(...)
  30. {
  31. int address = (int)ptr + position;
  32. printf("END OF 0x%x\n", address);
  33. done_flag = true;
  34. }
  35. }
  36. getchar();
  37. }

7.png

随意选取一个地址即可,这里选的是0x76830e07


0x02 查找ExitProcess API

MessageBoxA是动态链接库user32.dll的导出函数,ExitProcess是kernel32.dll的导出函数。需要找到这两个函数的内存地址,通常使用的方法是使用depends工具获得动态链接库基址和函数偏移地址计算得到。由于安装的depends工具有点问题,还可以使用另一种方法,编译一段使用该函数的C程序,在Ollydbg中跟随查找到相应内存地址。

  1. #include <stdio.h>
  2. #include <windows.h>
  3. int main()
  4. {
  5. MessageBox(NULL,TEXT("title"),TEXT("content"),MB_OK);
  6. exit(0);
  7. }

2.png


0x03 制作shellcode

MessageBoxA内存地址:0x767C7E60
exit(0)内存地址:0x764E6420
jmp esp内存地址:0x76830e07
3.png

将相应的汇编转换为机器码,然后修改输入文件,总共修改3处。
4.png

用ollydbg运行程序,查看栈区情况。与Lab2的shellcode不同的是,此时有效shellcode位于栈下方(高地址),通过jmp esp跳转执行。
5.png

6.png

8.png
这样的shellcode只能保证能在本机上准确执行,在其他机器上就行不通了,更进一步的shellcode需要实现动态查找API地址的功能。


0x05 通用shellcode和shellcode编码技术

关于这一部分,对汇编和windows编程基础过于薄弱,所以只是简单的了解。shellcode的编码原理如图,但是自己编写编码器和解码器是很麻烦的,所以通常可以借助metaspploit进行编码。
9.png