[转载]在C中嵌入机器码的一种方式
信息来源:开放实验室 (openlab.nwpu.edu.cn) 【Visual C++】专栏以下程序用VC6.0 CL编译器编译
编译参数 : cl test.c /link kernel32.lib
程序在Win95下测试通过,运行结果:打开一个资源管理器
简要说明:
机器码在程序函数test中buffer里
在test中通过
push addr buffer ; push ebp-80
ret 0
跳入机器码
这段代码如下工作
[code]push addr string1 ; string1 : "shell32.dll"
call LoadLibrary
invoke ShellExecute NULL,addr string2,0,0,0,5 ; string2 : "open" 打开资源管理器
push addr ExitProcess
ret 0 ;结束进程
#include<stdio.h>
#include<windows.h>
int test()
{
// Follow Addr Tested on Windows95
//LoadLibrary Addr: 0BFF775F3h
//GetProcAddress Addr: 0BFF76DD8h
//ShellExecute Addr: 07FDE9211h
//ExitProcess Addr: 0bff8b191h
char buffer[80]=
{
0xEB,0x1E, //jmp @call
0x5D, //pop ebp @jm
0x55, //push ebp
0xFF,0x55,0x11, //call dword ptr [ebp+11h]
0x6A,0x05, //push 5
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0x8B,0xC5, //mov eax,ebp
0x83,0xC0,0x0C, //add eax,0Ch
0x50, //push eax
0x6A,0x00, //push 0
0xFF,0x55,0x15, //call dword ptr [ebp+15h]
0x68,0x91,0xB1,0xF8,0xBF, //push 0BFF8B191h ExitProcess 地址
0xC3, //ret
0xE8,0xDD,0xFF,0xFF,0xFF, //call @jm @call
's','h','e','l','l','3','2','.','d','l','l',0,
'o','p','e','n',0,
0xf3,0x75,0xf7,0xbf, //LoadLibrary 地址
0x11,0x92,0xde,0x7f //ShellExecute 地址
};
_asm
{
pop edi
pop esi
pop ebx
sub ebp,80
push ebp
ret 0
}
}
void main()
{
HINSTANCE hw = LoadLibrary("user32.dll");
// FARPROC fp = GetProcAddress(hw,"ShellExecute");
// ShellExecute(0,"open",0,0,0,5);
// printf("ShellExecute addr :%p",ShellExecute);
/* printf("LoadLibrary Addr :%p\n",LoadLibrary);
fp = GetProcAddress(hw,"GetProcAddress");
printf("GetProcAddress Addr: %p\n",fp);
printf("GetProcAddress Addr: %p\n",GetProcAddress);
*/
printf("%i\n",test());
}[/code] test() 正确返回代码已经被我截获
test()
{
}
对应为:
;test()
;{
push ebp
mov ebp,esp ; 现在ebp+4 处为test返回地址
sub esp,80 ;为buffer[80]留空间 过ebp-80处为buffer[0]地址
. . . . . . .
; test()准备返回
add esp,80 ;修正esp dword ptr [ esp] 为 保存的ebp值 dword ptr[esp+4] 为 test返回地址
pop ebp ;现在栈顶为test返回值
ret 0 ;返回调用test的main函数中
;}
而
_asm
{
}
对应汇编为
;_asm
;{
push ebx
push esi
push edi
. . . .
pop edi
pop esi
pop ebx
;}
现在是
test()
{
char buffer[80];
_asm
{
pop edi ;抵消 _asm进入时加入的三个push
pop esi
pop ebx
sub ebp,80 ;ebp现在为buffer入口
push ebp ;现在栈顶为buffer入口地址 下条ret 将以此地址作为返回地址,进入buffer
ret 0 ;进入buffer ,注意ret 之后esp+80也是buffer尾部 esp+84是ebp esp+88是test
;正确返回地址
}
}
在buffer中的代码有如下 这部分相当是test()函数最后准备返回时的代码,参加上面test()
add esp,80 ;现在栈顶是ebp
pop ebp ;现在栈顶是test返回地址
ret 0 ;正确返回 好了又回到了main()
还有win32中是32位已经是在同一个线性空间cs;ss;ds等已经失去dos下ss:sp cs:ip
等功能,而是直接在空间中以eip, esp等来寻址 当然用能到堆栈中执行
真正有难度的东东是机器嘛那一段,想想里面有需要的string,而且还要string的地址
解觉办法是依赖jmp 和call ,他们都是用相对当前地址跳转,尤其是call 会保存下一条指令地址
我们把string放在call的下面call调用后就会在栈顶压入string的地址 ^_*
那段机器码如下
jmp sh_call ;在sh_call处是 call sh_jm 有回来了!! 但此时已压入了string的地址
sh_jm:
pop ebp ; ebp中为string的地址
. . . . . . .
sh_call:
call sh_jm
string db . . . .
编译参数没什么意义就是让程序能编译通过
附cl产生的汇编程序
都可以在 [url]ftp://202.117.82.4/asm/asm-c/[/url]下找到
; Listing generated by Microsoft (R) Optimizing Compiler Version 13.00.8905
TITLE shellcode2.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
INCLUDELIB LIBC
INCLUDELIB OLDNAMES
PUBLIC _test
; Function compile flags: /Odt
_TEXT SEGMENT
_buffer$ = -80
_test PROC NEAR
; File c:\work\asm-c\shellcode2.c
; Line 4
push ebp
mov ebp, esp
sub esp, 80 ; 00000050H
push ebx
push esi
push edi
; Line 14
mov BYTE PTR _buffer$[ebp], -21 ; ffffffebH
mov BYTE PTR _buffer$[ebp+1], 36 ; 00000024H
; Line 15
mov BYTE PTR _buffer$[ebp+2], 93 ; 0000005dH
; Line 16
mov BYTE PTR _buffer$[ebp+3], 104 ; 00000068H
mov BYTE PTR _buffer$[ebp+4], -57 ; ffffffc7H
mov BYTE PTR _buffer$[ebp+5], -3 ; fffffffdH
mov BYTE PTR _buffer$[ebp+6], 99 ; 00000063H
mov BYTE PTR _buffer$[ebp+7], 0
; Line 17
mov BYTE PTR _buffer$[ebp+8], -1
mov BYTE PTR _buffer$[ebp+9], 85 ; 00000055H
mov BYTE PTR _buffer$[ebp+10], 17 ; 00000011H
; Line 19
mov BYTE PTR _buffer$[ebp+11], -125 ; ffffff83H
mov BYTE PTR _buffer$[ebp+12], -8 ; fffffff8H
mov BYTE PTR _buffer$[ebp+13], 0
; Line 20
mov BYTE PTR _buffer$[ebp+14], 116 ; 00000074H
mov BYTE PTR _buffer$[ebp+15], 17 ; 00000011H
; Line 22
mov BYTE PTR _buffer$[ebp+16], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+17], 5
; Line 23
mov BYTE PTR _buffer$[ebp+18], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+19], 0
; Line 24
mov BYTE PTR _buffer$[ebp+20], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+21], 0
; Line 25
mov BYTE PTR _buffer$[ebp+22], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+23], 0
; Line 28
mov BYTE PTR _buffer$[ebp+24], -125 ; ffffff83H
mov BYTE PTR _buffer$[ebp+25], -59 ; ffffffc5H
mov BYTE PTR _buffer$[ebp+26], 12 ; 0000000cH
; Line 29
mov BYTE PTR _buffer$[ebp+27], 85 ; 00000055H
; Line 30
mov BYTE PTR _buffer$[ebp+28], 106 ; 0000006aH
mov BYTE PTR _buffer$[ebp+29], 0
; Line 32
mov BYTE PTR _buffer$[ebp+30], -1
mov BYTE PTR _buffer$[ebp+31], 85 ; 00000055H
mov BYTE PTR _buffer$[ebp+32], 9
; Line 34
mov BYTE PTR _buffer$[ebp+33], -125 ; ffffff83H
mov BYTE PTR _buffer$[ebp+34], -60 ; ffffffc4H
mov BYTE PTR _buffer$[ebp+35], 80 ; 00000050H
; Line 35
mov BYTE PTR _buffer$[ebp+36], 93 ; 0000005dH
; Line 36
mov BYTE PTR _buffer$[ebp+37], -61 ; ffffffc3H
; Line 37
mov BYTE PTR _buffer$[ebp+38], -24 ; ffffffe8H
mov BYTE PTR _buffer$[ebp+39], -41 ; ffffffd7H
mov BYTE PTR _buffer$[ebp+40], -1
mov BYTE PTR _buffer$[ebp+41], -1
mov BYTE PTR _buffer$[ebp+42], -1
; Line 38
mov BYTE PTR _buffer$[ebp+43], 115 ; 00000073H
mov BYTE PTR _buffer$[ebp+44], 104 ; 00000068H
mov BYTE PTR _buffer$[ebp+45], 101 ; 00000065H
mov BYTE PTR _buffer$[ebp+46], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+47], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+48], 51 ; 00000033H
mov BYTE PTR _buffer$[ebp+49], 50 ; 00000032H
mov BYTE PTR _buffer$[ebp+50], 46 ; 0000002eH
mov BYTE PTR _buffer$[ebp+51], 100 ; 00000064H
mov BYTE PTR _buffer$[ebp+52], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+53], 108 ; 0000006cH
mov BYTE PTR _buffer$[ebp+54], 0
; Line 39
mov BYTE PTR _buffer$[ebp+55], 111 ; 0000006fH
mov BYTE PTR _buffer$[ebp+56], 112 ; 00000070H
mov BYTE PTR _buffer$[ebp+57], 101 ; 00000065H
mov BYTE PTR _buffer$[ebp+58], 110 ; 0000006eH
mov BYTE PTR _buffer$[ebp+59], 0
; Line 40
mov BYTE PTR _buffer$[ebp+60], -13 ; fffffff3H
mov BYTE PTR _buffer$[ebp+61], 117 ; 00000075H
mov BYTE PTR _buffer$[ebp+62], -9 ; fffffff7H
mov BYTE PTR _buffer$[ebp+63], -65 ; ffffffbfH
; Line 41
mov BYTE PTR _buffer$[ebp+64], 17 ; 00000011H
mov BYTE PTR _buffer$[ebp+65], -110 ; ffffff92H
mov BYTE PTR _buffer$[ebp+66], -34 ; ffffffdeH
; Line 42
mov BYTE PTR _buffer$[ebp+67], 127 ; 0000007fH
xor eax, eax
mov DWORD PTR _buffer$[ebp+68], eax
mov DWORD PTR _buffer$[ebp+72], eax
mov DWORD PTR _buffer$[ebp+76], eax
; Line 46
pop edi
; Line 47
pop esi
; Line 48
pop ebx
; Line 55
sub ebp, 80 ; 00000050H
; Line 56
push ebp
; Line 57
ret 0
; Line 60
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_test ENDP
_TEXT ENDS
PUBLIC _main
EXTRN _printf:NEAR
_DATA SEGMENT
$SG53167 DB '%i', 0aH, 00H
; Function compile flags: /Odt
_DATA ENDS
_TEXT SEGMENT
_main PROC NEAR
; Line 62
push ebp
mov ebp, esp
; Line 75
call _test
push eax
push OFFSET FLAT:$SG53167
call _printf
add esp, 8
; Line 77
xor eax, eax
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
页:
[1]