|
本帖最后由 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的方法制作成机器码进行调用呢? |
|