【内联汇编】如何通过地址来调用某函数

aquastar 2010-12-19 10:00:46

__asm
{
mov eax, fs:[0x30] ;point to PEB
mov eax, [eax + 0x0C] ;point to _PEB_LDR_DATA
mov eax, [eax + 0x0C] ;point to InLoadOrderModuleList
mov eax, [eax] ;InLoadOrderLinks of this process
mov eax, [eax] ;InLoadOrderLinks of ntdll address
mov eax, [eax + 0x18] ;DllBase of kernel32 address
mov edi,eax ;edi poin to kernel32

//mov ebp,esp;
//sub esp,100;
mov eax,[edi+3ch] ;edx point to pe header
mov edx,[edi+eax+78h] ;edx point to RVA of export table
add edx,edi ;edx point to VA of export table
mov ecx,[edx+18h] ;ecx point to the number of functions of export name table
mov ebx,[edx+20h] ;ebx point to RVA of export name table
add ebx,edi ;ebx point to VA of export name table

search:
dec ecx ;loop counter ecx minusitself
mov esi,[ebx+ecx*4] ;esi get RVA of function name from last
add esi, edi; ;esi get VA of it
mov eax,0x50746547 ;eax get PteG("GetP")
cmp [esi],eax ;compare [esi] with current block
jne search
mov eax,0x41636f72 ;eax get Acor("rocA")
cmp [esi+4],eax ;compare second half
jne search
mov ebx,[edx+24h] ;ebx point to RVA of export index table
add ebx,edi ;ebx point to VA of export index table
mov cx,[ebx+ecx*2] ;
mov ebx,[edx+1ch] ;ebx point to RVA of export address table
add ebx,edi ;ebx point to VA of export address table
mov eax,[ebx+ecx*4] ;eax point to RVA of function
add eax,edi ;eax point to VA of function
mov [ebp+76],eax ;restore somewhere

call GetProAddress:
push 0;
push DWORD PTR 0x57656C ; leW(" leA")
push DWORD PTR 0x69466574 ;iFet("teFi")
push DWORD PTR 0x61657243 ;aerC("Crea")
push esp
push edi
call [ebp+76]
mov [ebp+80],eax

call CreateFileA:
push 0
push 0
push 2
push 0
push 0
push 40000000h
push offset string "C:\\test\\test.txt"
call [ebp+80];




}


上面是网上的代码加上自己一点点修改,目的是先找到kernel32,然后在找到getProcAdress,然后拿到CreateFileA地址,然后调用它,前面的步骤都得到正确结果了,
[B]1[/B] 但是调用的call CreateFileA:部分出问题了,那个函数原型例子是
CreateFileA("c:\\test\\test.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,NULL,NULL);不知道是不是这么调用
,其实callGetProAddress我也不明白,参数应该就只有kernel32地址和函数名,为什么要push 0;(用来截断字符?)和push esp

[B]2[/B]序数表我调试的结果是序数表是从2开始计数的,不知道自己有没有调错,下面是某此调试的结果,75a87848 是我查到的序数表地址,如果这样计数序数,那么再查地址表的时候岂不是多了,还是说地址表也刚好差2,还有存序数为什么用cx不用ecx
75a87848 02 00 03 00 04 00 05 00-06 00 07 00 08 00 09 00 ................
75a87858 0a 00 0b 00 0c 00 0d 00-0e 00 0f 00 10 00 11 00 ................
75a87868 12 00 13 00 14 00 15 00-16 00 17 00 18 00 19 00 ................
75a87878 1a 00 1b 00 1c 00 1d 00-1e 00 1f 00 20 00 21 00 ............ .!.
75a87888 22 00 23 00 24 00 25 00-26 00 27 00 28 00 29 00 ".#.$.%.&.'.(.).
75a87898 2a 00 2b 00 00 00 2c 00-2d 00 2e 00 2f 00 30 00 *.+...,.-.../.0.
75a878a8 31 00 32 00 33 00 34 00-35 00 36 00 37 00 38 00 1.2.3.4.5.6.7.8.
75a878b8 39 00 3a 00 3b 00 3c 00-3d 00 3e 00 3f 00 40 00 9.:.;.<.=.>.?.@.
...全文
548 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
aquastar 2010-12-21
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 zara 的回复:]
引用 10 楼 aquastar 的回复:
一个寄存器里存着一个函数的地址比如是0x76540000,我需要打印到文件,打印是打印了,但是 00 00 54 76 这么给我解释出来的,一般应该如何输出,一个个的取?

你这个应该是从内存里逐字节输出的吧,这个顺序是内存里的存放顺序,即所谓的 little endian 模式。如果是要输出一个 dword,就从其高位、每 4 个二进制位为一组开……
[/Quote]

大概也知道,不过输出的是16进制,要转换成对应的ASCII码,因为不太熟悉汇编,这段具体应该怎么做?
aquastar 2010-12-21
  • 打赏
  • 举报
回复
7楼的问题我解决了,自己代码的问题..
zara 2010-12-21
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 aquastar 的回复:]
一个寄存器里存着一个函数的地址比如是0x76540000,我需要打印到文件,打印是打印了,但是 00 00 54 76 这么给我解释出来的,一般应该如何输出,一个个的取?
[/Quote]
你这个应该是从内存里逐字节输出的吧,这个顺序是内存里的存放顺序,即所谓的 little endian 模式。如果是要输出一个 dword,就从其高位、每 4 个二进制位为一组开始输出了
aquastar 2010-12-21
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zara 的回复:]
多个拼接下再 push,好像反而过于复杂了吧。直接 push eax 就是了,后来就只使用 al 便是。
[/Quote]


mov eax, [ebp+84]
mov ecx, 8
l_:
push eax
and al, 0fh
add al, '0'
cmp al, '9'
jna fors
add al, 7
fors:
mov bl,al; 保存或输出 al 中的字符

pop eax
ror eax, 4
push bl
loop l_


改成这样,是正常输出了,可惜由于压入的都是32位,我只用了8位,导致输出的有些空格,应该拼成ebx,不过又多了些逻辑吧,
zara 2010-12-21
  • 打赏
  • 举报
回复
多个拼接下再 push,好像反而过于复杂了吧。直接 push eax 就是了,后来就只使用 al 便是。
aquastar 2010-12-21
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zara 的回复:]
Assembly code
; 或者,可以象是这样?
mov eax, 76540000h
mov ecx, 8
l_:
rol eax, 4
push eax
and al, 0fh
add al, '0'
cmp al, '9'
jna @f
add al, 7
@@:
; 保存或输出 al 中的字符
po……
[/Quote]

恩是这个,不过内联汇编不能用@@,@f,我就直接改个字符串,程序ok的,最后一个问题洛~

我想把这个字串接在我已经push好的字串中,

mov eax, [ebp+84]
mov ecx, 8
l_:
rol eax, 4
push eax
and al, 0fh
add al, '0'
cmp al, '9'
jna fors
add al, 7
fors:
push al; 保存或输出 al 中的字符
pop eax
loop l_
push 0x20656c69
push 0x20656c69
; many push


push al好像是不行的,打出来的是不是调试的结果
我又想是不是可以把eax拼成一个ebx,再push
zara 2010-12-21
  • 打赏
  • 举报
回复
; 或者,可以象是这样?
mov eax, 76540000h
mov ecx, 8
l_:
rol eax, 4
push eax
and al, 0fh
add al, '0'
cmp al, '9'
jna @f
add al, 7
@@:
; 保存或输出 al 中的字符
pop eax
loop l_
; ...
aquastar 2010-12-20
  • 打赏
  • 举报
回复
一个寄存器里存着一个函数的地址比如是0x76540000,我需要打印到文件,打印是打印了,但是 00 00 54 76 这么给我解释出来的,一般应该如何输出,一个个的取?
夜鹰 2010-12-20
  • 打赏
  • 举报
回复
由Windows版移至汇编语言版。
zara 2010-12-20
  • 打赏
  • 举报
回复
创建文件不能成功,在调试软件里看看 LastError 是什么错误了。最可能的就是文件名不正确吧,比如路径 test 不存在,结束的 00 字节有吗,……
aquastar 2010-12-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 hxp2k6 的回复:]
1.push 0 是 表明做为函数名的字符串结束;push esp:esp是一个指向字符串“CreateFileA”的指针,实际上这个push esp才是函数GetProcAddress的参数之一,push edi:edi指向字符串“kernel32.dll”做为GetProcAddress的第二个参数,然后调用函数GetProcAddress找到函数CreateFileA,从eax返回,调用结束……
[/Quote]
我上面的内联汇编,如此push参数调用,

01101436 mov esi,esp
01101438 push 0
0110143A push 0
0110143C push 2
0110143E push 0
01101440 push 0
01101442 push 40000000h
01101447 push offset string "c:\\test\\test.txt" (110573Ch)

但是报 “第二操作数”中的内联汇编语法错误;找到“bad token” 不能这么压啊?
aquastar 2010-12-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zara 的回复:]
色播病毒 FakeQVod 里用的好些就是这个代码?
1. 函数调用各个参数的说明,可以参考 msdn 的,比较详细,甚至还有例子。那个 push 0 是表明作为函数名的字符串的结束的。
2. 序号表这块,确实有些乱!详细说明可以参考侯捷的那本“Windows 95 系统程式设计大奥秘”里“PE与COFF OBJ 档案格式”中输出节部分。
[/Quote]

msdn我查过,参数我确定,如下是在vs中反汇编调试的结果

CreateFileA("c:\\test\\test.txt",0x40000000L,0,0,2,0,0);
01101436 mov esi,esp
01101438 push 0
0110143A push 0
0110143C push 2
0110143E push 0
01101440 push 0
01101442 push 40000000h
01101447 push offset string "c:\\test\\test.txt" (110573Ch)
0110144C call dword ptr [__imp__CreateFileA@28 (11081A4h)]
01101452 cmp esi,esp
01101454 call @ILT+315(__RTC_CheckEsp) (1101140h)

CreateFileA("c:\\test\\test.txt",0x40000000L,0,0,2,0,0);是执行成功了的,参数都换成了实际的数值,都是常用设置就是创建一个文件,对应的反汇编的这一段

01101436 mov esi,esp
01101438 push 0
0110143A push 0
0110143C push 2
0110143E push 0
01101440 push 0
01101442 push 40000000h
01101447 push offset string "c:\\test\\test.txt" (110573Ch)

放到内联汇编中,貌似不能成功执行,为什么呢
hxp2k6 2010-12-20
  • 打赏
  • 举报
回复
1.push 0 是 表明做为函数名的字符串结束;push esp:esp是一个指向字符串“CreateFileA”的指针,实际上这个push esp才是函数GetProcAddress的参数之一,push edi:edi指向字符串“kernel32.dll”做为GetProcAddress的第二个参数,然后调用函数GetProcAddress找到函数CreateFileA,从eax返回,调用结束之后把返回值存入[ebp+80].
2.至于第二问,不是到是不是因为编码格式的问题,比如unicode编码方式是widechar,一个字符占用2个字节......
zara 2010-12-20
  • 打赏
  • 举报
回复
色播病毒 FakeQVod 里用的好些就是这个代码?
1. 函数调用各个参数的说明,可以参考 msdn 的,比较详细,甚至还有例子。那个 push 0 是表明作为函数名的字符串的结束的。
2. 序号表这块,确实有些乱!详细说明可以参考侯捷的那本“Windows 95 系统程式设计大奥秘”里“PE与COFF OBJ 档案格式”中输出节部分。
chzhn 2010-12-20
  • 打赏
  • 举报
回复
char* cFileName = "C:\\test\\test.txt";

push 0
push 0
push 2
push 0
push 0
push 40000000h
lea eax,[cFileName]
mov eax,[eax]
push eax
call [ebp+80];
zara 2010-12-20
  • 打赏
  • 举报
回复
直接上来个最简单的有这问题的可执行文件看看?
aquastar 2010-12-20
  • 打赏
  • 举报
回复
在确认拿到正确的CreateFileA的地址后放在某地比如放在 [ebp+80]
我们参考函数原型CreateFileA("c:\\test\\test.txt",0x40000000L,0,0,2,0,0)
其中后面几个常量我都换成实际的值,并且在vc,vs下成功执行


用vs反汇编得到这句的反汇编是
CreateFileA("c:\\test\\test.txt",0x40000000L,0,0,2,0,0);
00301453 mov esi,esp
00301455 push 0
00301457 push 0
00301459 push 2
0030145B push 0
0030145D push 0
0030145F push 40000000h
00301464 push offset string "c:\\test\\test.txt" (30573Ch)
00301469 call dword ptr [__imp__CreateFileA@28 (3081A4h)]
0030146F cmp esi,esp
00301471 call @ILT+315(__RTC_CheckEsp) (301140h)


于是我想仿造调用写成
push 0
push 0
push 2
push 0
push 0
push 40000000h
push offset string "c:\\test\\test.txt"
call [ebp+80]


红色一行报错为“第二操作数”中的内联汇编语法错误;找到“bad token” + “操作码”中的内联汇编语法错误;找到“bad token”


于是我们想用<0day安全>P108类似方法,最开始压入并记下地址,把保存地址当做参数压入
xor ebx,ebx
push ebx ;for cutting string
push 0x74 ;t("t")
push 0x78742e31 ;xt.1("1.tx")
mov eax,esp
push 0
push 0
push 2
push 0
push 0
push 40000000h
push eax
call [ebp+80]


希望在同目录生成一个1.txt文件,还是失败
于是再试汇编外定义变量var_path,然后push offset var_path,仍然失败
char var_path[]="hello world";
__asm
{
lea eax,var_path
push eax
}

OllyDBG貌似参数也传对了,call的时候就出错了,不知道可能的错误在哪里

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧