0x00前言

shellcode是一段用于利用软件漏洞而执行的代码,shellcode为16进制(0x,\x)的机器码,因为经常让攻击者获得shell而得名
同样 shellcode常常用机器语言编写,可在寄存器溢出后,强行塞入一段可以让CPU执行的shellcode机器码,让CPU执行我们的任意代码

0x01shellcode的分类

shellcode按照攻击者执行位置可以分为shelllcode和远程shellcode
本地shellcode:
本地运行的shellcode经常用于利于软件漏洞提升权限,例如linux下由普通权限提升,或者其他软件,服务等方式执行shellcode来获取权限
远程shellcode:
常常利用特定的软件或服务漏洞,获取特定的shellcode,在经过C或者python编写远程工具程序,进而获取对方管理员权限

0x02使用VC6编写shellcode

终于还是拿出我n久没用过,差点要卸载的vc6了
新建工程->01->”简单的helloworld程序”
image.png
编译运行没有问题,现在我们改一下代码,让他弹窗

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. int main(int argc, char* argv[])
  4. {
  5. MessageBoxA(NULL,NULL,NULL,0);
  6. return 0;
  7. }

image.png
查看一下反汇编,我们需要知道MessageBoxA的内存地址
Build——>Start Debug——>Run to Cursor,弹出Debug小窗口,点最后一个……
image.png
因为这里是这个函数的指针,而不是真实地址,来到0x0042a2ac处,因为是从高位到地位保存,所以要倒着取,就是0x76990A50,就是弹窗函数的地址
将这段代码保存,回到源代码处:
将原来写的messageboxa函数删掉,导入动态链接库"user32.dll"

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. int main(int argc, char* argv[])
  4. {
  5. LoadLibrary("user32.dll");
  6. __asm{
  7. push 0
  8. push 0
  9. push 0
  10. mov eax,0x76990A50
  11. call eax
  12. }
  13. return 0;
  14. }

成功弹窗,接下来,反汇编调试,记录下弹窗汇编的内存中十六进制机器码
image.png
0x0040103c是起始位置,而0x401047就是结尾地址,地址中存放的就是十六进制机器码
image.png
所以我们取出:
6A 00 6A 00 6A 00 B8 50 0A 99 76 FF
定义一个char的数组,转化为
char shellcode[]="\x6A\x00\x6A\x00\x6A\x00\xB8\x50\x0A\x99\x76\xFF";
stop!
这里就需要在介绍一个知识点:(*(void(*)())&shellcode)();:
1.后面的括号说明这是一个函数调用,去掉
2.&shellcode就是取这个变量的内存地址,也可以改成&shellcode[0]
3. 剩下(void(*)(void))&ShellCode,这是一个强制类型转换,后面的 &ShellCode 是被转化对象,去掉
4.剩下void(*)(void) 就是一个类型了,这类型是一个函数指针,前面的void表示这个函数指针指向的函数返回类型为 void,后面的 (void)这个函数指针指向的函数的参数为 void
5.剩下 void(*)(void) 就是一个类型了,这类型是一个函数指针,前面的void表示这个函数指针指向的函数返回类型为 void,后面的(void)这个函数指针指向的函数的参数为 void
本人也是网上看了很久,终于理解了,现在整个完整的C语言shellcode就是这样子的:

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. int main(int argc, char* argv[])
  4. {
  5. LoadLibrary("user32.dll");
  6. char shellcode[]="\x6A\x00\x6A\x00\x6A\x00\xB8\x50\x0A\x99\x76\xFF";
  7. (*(void(*)())&shellcode)();
  8. return 0;
  9. }

但是运行后,是弹窗了,但是那是报错弹窗,并不是我们shellcode的结果,说明代码有问题
image.png
后面通过排错等方法,终于 发现了bug所在的位置,还记得我们上面查push 0call eax,这个图吧,没错!0x00101047只是那行汇编代码的其实地址,应该再往后偏移两个字节,也就是还需要算上D0 33
image.png
将shellcode改为:
char shellcode[]="\x6A\x00\x6A\x00\x6A\x00\xB8\x50\x0A\x99\x76\xFF\xD0\x33";
成功弹窗!!!!
image.png
目前演示的shellcode只是弹出个无用消息框,当然根据你的需求,可以让shellcode执行更加多样化的操作