找回密码
 加入
搜索
查看: 8946|回复: 10

[系统综合] 关于au3调用机器码的几点疑问【已解决】

  [复制链接]
发表于 2013-5-18 20:29:37 | 显示全部楼层 |阅读模式
本帖最后由 gto250 于 2013-5-20 21:39 编辑

最近又重新学习了一下ward大神的《AutoIt 機械碼的製作與調用》的几个贴子。
然后按图索骥,找了一个C的源码,试着制作了一下,几番摸索,竟然成功了。
因为对C语言,对asm汇编语言都不怎么懂,怎么成功的,基本上就靠运气了,只知其然不知其所以然。
现将代码附上,问题在后面。
C源码
int is_vowel(char a)
{
    switch(a)
    {
    case 'a': case 'A':
    case 'e': case 'E':
    case 'i': case 'I':
    case 'o': case 'O':
    case 'u': case 'U':
        return 1; break;
    default: 
        return 0; break;
    }
}
int count_vowel(const char *s)
{
    int num;
    if(s[0] == '\0')
        num = 0;
    else
    {
        if(is_vowel(s[0]))
            num = 1 + count_vowel(&s[1]);
        else
            num = count_vowel(&s[1]);
    }
    return num;
}
这是一段计算一个字母字符串中元音的个数的代码,找的代码有点无聊,不过因为这个简单。

制作成功后的代码:
#Include <Memory.au3>

Global $_xxHash_CodeBuffer, $_xxHash_CodeBufferPtr
Global $_xxHash_FastPtr, $_xxHash_StrongPtr


MsgBox(0,"",_xxHash_Strong("abcdefguvo"))
_xxHash_Shutdown()



Func _xxHash_Shutdown()
        $_xxHash_CodeBuffer = 0
        _MemVirtualFree($_xxHash_CodeBufferPtr, 0, $MEM_RELEASE)
EndFunc
Func _xxHash_Startup()
        If Not IsDllStruct($_xxHash_CodeBuffer) Then
                Local $Code

$Code = '0xFF01EB04FF02EB195589E58A550883EA4131C080FA3477070FB6D20FBE424F5DC35589E55653518B75084631DB8A46FF84C074140FBEC0890424E8C9FFFFFF83F80183DBFF46EBE589D85A5B5E5DC30100000001000000010000000000010000000000010000000000000000000000010000000100000001000000000001000000000001000000'

Local $Offset_Fast = (StringInStr($Code, "FF01") + 1) / 2
Local $Offset_Strong = (StringInStr($Code, "FF02") + 1) / 2
Local $Opcode = Binary($Code)
$_xxHash_CodeBufferPtr = _MemVirtualAlloc(0, BinaryLen($Opcode), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
$_xxHash_CodeBuffer = DllStructCreate("byte[" & BinaryLen($Opcode) & "]", $_xxHash_CodeBufferPtr)
       DllStructSetData($_xxHash_CodeBuffer, 1, $Opcode)
       $_xxHash_StrongPtr = $_xxHash_CodeBufferPtr + $Offset_Strong
           
 Local $TablePtr1 = DllStructCreate("ptr", $_xxHash_CodeBufferPtr + 0x17)
 DllStructSetData($TablePtr1, 1, DllStructGetData($TablePtr1, 1) + $_xxHash_CodeBufferPtr)



       OnAutoItExitRegister("_xxHash_Shutdown")
        EndIf
EndFunc

Func _xxHash_Strong($Data)
        If Not IsDllStruct($_xxHash_CodeBuffer) Then _xxHash_Startup()

       ; $Data = Binary($Data)

        Local $Ret = DllCallAddress("uint:cdecl", $_xxHash_StrongPtr, "str",$Data)
        Return $Ret[0]
EndFunc
按照ward写的例子修改的,变量都没怎么改动。

asm转换后的代码
use32
db 0xFF,0x01
jmp _is_vowel

db 0xFF,0x02
jmp _count_vowel


_is_vowel:
        push    ebp                                     ; 0000 _ 55
        mov     ebp, esp                                ; 0001 _ 89. E5
        mov     dl, byte [ebp+8H]                       ; 0003 _ 8A. 55, 08
        sub     edx, 65                                 ; 0006 _ 83. EA, 41
        xor     eax, eax                                ; 0009 _ 31. C0
        cmp     dl, 52                                  ; 000B _ 80. FA, 34
        ja      ?_001                                   ; 000E _ 77, 0A
        movzx   edx, dl                                 ; 0010 _ 0F B6. D2
        movsx   eax, byte [_CSWTCH.1+edx]               ; 0013 _ 0F BE. 82, 00000000(d)
?_001:  pop     ebp                                     ; 001A _ 5D
        ret                                             ; 001B _ C3

_count_vowel:; Function begin
        push    ebp                                     ; 001C _ 55
        mov     ebp, esp                                ; 001D _ 89. E5
        push    esi                                     ; 001F _ 56
        push    ebx                                     ; 0020 _ 53
        push    ecx                                     ; 0021 _ 51
        mov     esi, dword [ebp+8H]                     ; 0022 _ 8B. 75, 08
        inc     esi                                     ; 0025 _ 46
        xor     ebx, ebx                                ; 0026 _ 31. DB
?_002:  mov     al, byte [esi-1H]                       ; 0028 _ 8A. 46, FF
        test    al, al                                  ; 002B _ 84. C0
        jz      ?_003                                   ; 002D _ 74, 14
        movsx   eax, al                                 ; 002F _ 0F BE. C0
        mov     dword [esp], eax                        ; 0032 _ 89. 04 24
        call    _is_vowel                               ; 0035 _ E8, FFFFFFC6
        cmp     eax, 1                                  ; 003A _ 83. F8, 01
        sbb     ebx, -1                                 ; 003D _ 83. DB, FF
        inc     esi                                     ; 0040 _ 46
        jmp     ?_002                                   ; 0041 _ EB, E5

?_003:  mov     eax, ebx                                ; 0043 _ 89. D8
        pop     edx                                     ; 0045 _ 5A
        pop     ebx                                     ; 0046 _ 5B
        pop     esi                                     ; 0047 _ 5E
        pop     ebp                                     ; 0048 _ 5D
        ret                                             ; 0049 _ C3

_CSWTCH.1:                                              ; byte
        db 01H, 00H, 00H, 00H, 01H, 00H, 00H, 00H       ; 0000 _ ........
        db 01H, 00H, 00H, 00H, 00H, 00H, 01H, 00H       ; 0008 _ ........
        db 00H, 00H, 00H, 00H, 01H, 00H, 00H, 00H       ; 0010 _ ........
        db 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H       ; 0018 _ ........
        db 01H, 00H, 00H, 00H, 01H, 00H, 00H, 00H       ; 0020 _ ........
        db 01H, 00H, 00H, 00H, 00H, 00H, 01H, 00H       ; 0028 _ ........
        db 00H, 00H, 00H, 00H, 01H, 00H, 00H, 00H       ; 0030 _ ........
存在的问题有以下几个:
1、运行效果不稳定,多次运行后会出现程序崩溃的情况
2、$TablePtr1 = DllStructCreate("ptr", $_xxHash_CodeBufferPtr + 0x17)这一句,虽然用0x17成功了。但是在汇编代码中 movsx   eax, byte [_CSWTCH.1+edx]               ; 0013 _ 0F BE. 82, 00000000(d)  ,_CSWTCH.1所在是在0x16,为什么用0x16就不成功?
3、因为对C根本就一窍不通,因此想知道,如果C代码中存在api调用的情况,能否也能按照ward的方法制作成机器码进行调用呢?
发表于 2013-5-19 00:19:51 | 显示全部楼层
需要改动的两处地方:
1、
$bCode = "0xFF01EB04FF02EB1C558BEC8A550883EA4133C080FA34770A0FB6D20FBE82520000005DC3558BEC5653518B75084633DB8A46FF84C074140FBEC0890424E8C6FFFFFF83F80183DBFF46EBE58BC35A5B5E5DC301000000010000000100000000000100000000000100000000000000000000000100000001000000010000000000010000000000010000000000000000000000"


2、
Local $TablePtr1 = DllStructCreate("ptr", $_xxHash_CodeBufferPtr + 0x1E)
DllStructSetData($TablePtr1, 1, DllStructGetData($TablePtr1, 1) + $_xxHash_CodeBufferPtr)
发表于 2013-5-19 07:50:40 | 显示全部楼层
根本看不懂,标记一下
 楼主| 发表于 2013-5-19 20:41:27 | 显示全部楼层
回复 2# pusofalse


    为什么和我生成的机器码不一样呢,对asm进行了修改吗?能说明一下吗?
发表于 2013-5-20 06:58:28 | 显示全部楼层
回复 4# gto250


2#的机器码翻译成汇编代码如下。不必在意0x1890000这个起始地址,只看其他指令相对于这个地址的偏移就好了。
01890000    FF01            inc     dword ptr [ecx]
01890002    EB 04           jmp     short 01890008
01890004    FF02            inc     dword ptr [edx]
01890006    EB 1C           jmp     short 01890024
_is_vowel:
01890008    55              push    ebp
01890009    8BEC            mov     ebp, esp
0189000B    8A55 08         mov     dl, byte ptr [ebp+8]
0189000E    83EA 41         sub     edx, 41
01890011    33C0            xor     eax, eax
01890013    80FA 34         cmp     dl, 34
01890016    77 0A           ja      short 01890022
01890018    0FB6D2          movzx   edx, dl
0189001B    0FBE82 52000000 movsx   eax, byte ptr [edx+52]
01890022    5D              pop     ebp
01890023    C3              retn
_count_vowel:
01890024    55              push    ebp
01890025    8BEC            mov     ebp, esp
01890027    56              push    esi
01890028    53              push    ebx
01890029    51              push    ecx
0189002A    8B75 08         mov     esi, dword ptr [ebp+8]
0189002D    46              inc     esi
0189002E    33DB            xor     ebx, ebx
01890030    8A46 FF         mov     al, byte ptr [esi-1]
01890033    84C0            test    al, al
01890035    74 14           je      short 0189004B
01890037    0FBEC0          movsx   eax, al
0189003A    890424          mov     dword ptr [esp], eax
0189003D    E8 C6FFFFFF     call    01890008
01890042    83F8 01         cmp     eax, 1
01890045    83DB FF         sbb     ebx, -1
01890048    46              inc     esi
01890049  ^ EB E5           jmp     short 01890030
0189004B    8BC3            mov     eax, ebx
0189004D    5A              pop     edx
0189004E    5B              pop     ebx
0189004F    5E              pop     esi
01890050    5D              pop     ebp
01890051    C3              retn
_CSWTCH.1:
01890052    0100            add     dword ptr [eax], eax
01890054    0000            add     byte ptr [eax], al
01890056    0100            add     dword ptr [eax], eax
01890058    0000            add     byte ptr [eax], al
0189005A    0100            add     dword ptr [eax], eax
0189005C    0000            add     byte ptr [eax], al
0189005E    0000            add     byte ptr [eax], al
01890060    0100            add     dword ptr [eax], eax
01890062    0000            add     byte ptr [eax], al
01890064    0000            add     byte ptr [eax], al
01890066    0100            add     dword ptr [eax], eax
01890068    0000            add     byte ptr [eax], al
0189006A    0000            add     byte ptr [eax], al
0189006C    0000            add     byte ptr [eax], al
0189006E    0000            add     byte ptr [eax], al
01890070    0000            add     byte ptr [eax], al
01890072    0100            add     dword ptr [eax], eax
01890074    0000            add     byte ptr [eax], al
01890076    0100            add     dword ptr [eax], eax
01890078    0000            add     byte ptr [eax], al
0189007A    0100            add     dword ptr [eax], eax
0189007C    0000            add     byte ptr [eax], al
0189007E    0000            add     byte ptr [eax], al
01890080    0100            add     dword ptr [eax], eax
01890082    0000            add     byte ptr [eax], al
01890084    0000            add     byte ptr [eax], al
01890086    0100            add     dword ptr [eax], eax
01890088    0000            add     byte ptr [eax], al
0189008A    0000            add     byte ptr [eax], al
0189008C    0000            add     byte ptr [eax], al
0189008E    0000            add     byte ptr [eax], al
 楼主| 发表于 2013-5-20 20:05:45 | 显示全部楼层
回复 5# pusofalse


    0FBE82 52000000 movsx 攀愀砀, byte ptr [edx+52]

我对比了一下,代码就在这个位置不一样,为什么你的代码中0FBE82 52000000,52后面的这些0是怎么来的,怎么样修改,才能实现和你一样的机器码?
发表于 2013-5-20 20:54:51 | 显示全部楼层
回复 6# gto250

0FBE82 XXXXXXXX、0FBE42 XX,都是movsx eax, byte ptr [edx+?]的机器码(?表示偏移),但0FBE82 XXXXXXXX可以寻址到4GB内存空间。0FBE42 XX,由于这里的XX只占一个字节的长度,因此最大内存寻址空间只有256字节。

movsx eax, byte ptr [edx+52]这一条汇编指令转换为机器码,可以是:
0FBE82 52000000
也可以是:
0FBE42 52

但是,寻址范围超出256字节以后,必须要使用0FBE82 XXXXXXXX形式,例如movsx eax, byte ptr [edx+01890000],这条指令只能转换为0FBE82 00008901。

显然对于movsx eax, byte ptr [edx+52]这一条指令来说,0FBE42 52相较于0FBE82 52000000,会占用更少的存储空间。你在编译C代码时,编译器会优先选用这种 长度比较短的指令,但是它不知道在编译之后、你还会修改其中的指令。

我在2#给出的机器码是按照你提供的、在OD中一条一条抄写过来的。到movsx eax, byte ptr [edx+52]这句时,特意使用了0FBE82 XXXXXXXX这种形式,我不知该如何让C编译器也选用这种形式。

评分

参与人数 1金钱 +50 贡献 +2 收起 理由
tryhi + 50 + 2 看不懂,加个分就对了

查看全部评分

 楼主| 发表于 2013-5-20 21:38:53 | 显示全部楼层
回复 7# pusofalse


    谢谢P版的回复,我想我已经有点理解了!
发表于 2013-5-24 00:22:45 | 显示全部楼层
太高深了!如何消化得了!
发表于 2013-5-24 18:02:46 | 显示全部楼层
掌握这个派什么用???
发表于 2013-6-5 19:01:06 | 显示全部楼层
莫名其妙

运行结果 = 4

您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-2 10:42 , Processed in 0.082731 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表