本文来至feiyue的分享!
最早从官网看到大神们在使用机器码(MCode)的时候,惊为天人,极为仰慕。
可惜一看介绍,需要先下载安装VC或者GCC,还有各种参数配置,总感觉很难,
因此很长时间都没有使用过。
后来慢慢尝试使用GCC,发现并不难,因为都是用命令行调用的,下载安装
GCC后根本不用配置,找到gcc.exe程序就可以在命令行使用了。
我推荐使用 TDM-GCC 64位版,可以在百度搜索 TDM-GCC 或在 官网 下载。
我成功地实现了自己写C语言代码并快速转化为机器码(MCode),真令人高兴。
比较了多种方法后,我把最简单的转化方式分享给大家,让大家也来使用机器码。
;===========================================
; 【AHK机器码生成器】 v2.0 By FeiYue
;
; 使用方法:
;
; 1、下载安装 TDM-GCC 64位版 到默认的安装目录,下载网址为:
; https://sourceforge.net/projects/tdm-gcc/files/latest/download
;
; 2、下载安装 TCC 的 32位 和 64位版 到AHK的目录,下载网址为:
; https://bellard.org/tcc/
;
; 3、选择C代码后,按【 Alt+C 】热键生成 GCC 编译的机器码,
; 或者按【 Ctrl+Alt+C 】热键生成 TCC 编译的机器码
;
;===========================================
!c:: ; 选择C代码后用 GCC 编译
^!c:: ; 选择C代码后用 TCC 编译
ClipSaved:=Clipboard
Clipboard=
Send {Ctrl Down}c{CtrlUp}
ClipWait, 3
s:=Clipboard, Clipboard:=ClipSaved
if s=
{
MsgBox, 4096, Error, The contents of the copy are empty!
Exit
}
Loop, 2 {
i:=A_Index-1
hex:=A_ThisLabel="!c" ? Gcc(s,i) : Tcc(s,i)
hex:=RegExReplace("xxx" hex, ".{1,50}", "`r`n . ""$0""")
s%i%:=StrReplace(hex, ". ""xxx", (i ? "x64":"x32") ":=""")
}
MsgBox, 4096, MCode has been generated! (32 + 64)
, % Clipboard:=s0 . s1
. "`r`n MCode(MyFunc, A_PtrSize=8 ? x64:x32)"
s:=s0:=s1:=""
return
Gcc(s, win64=0)
{
dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
;-----------------------------
exe1=C:\TDM-GCC-64\bin\gcc.exe
exe2=C:\TDM-GCC-64\bin\objcopy.exe
;-----------------------------
IfNotExist, %exe1%
{
MsgBox, 4096, Tip, Can't Find %exe1% !
return
}
FileDelete, % cpp:=dir "\5.c"
FileDelete, % obj:=dir "\5.obj"
FileDelete, % log:=dir "\5.log"
FileDelete, % bin:=dir "\5.bin"
FileAppend, %s%, %cpp%
SplitPath, ComSpec, cmd
Loop
{
Process, Exist, %cmd%
if !(pid:=ErrorLevel)
Break
Process, Close, %pid%
Process, WaitClose, %pid%, 3
}
arg:=(win64 ? "-m64":"-m32") . " -O2"
RunWait, %ComSpec% /c ""%exe1%" %arg% -c -o "%obj%" "%cpp%" 2>"%log%""
,, Hide
IfNotExist, %obj%
{
FileRead, s, %log%
FileDelete, %cpp%
FileDelete, %log%
MsgBox, 4096, Tip, C Compile Error`n`n%s%
return
}
RunWait, "%exe2%" -j .text -O binary "%obj%" "%bin%",, Hide
hex:=bin2hex(bin)
FileDelete, %cpp%
FileDelete, %obj%
FileDelete, %log%
FileDelete, %bin%
return, hex
}
Tcc(s, win64=0)
{
dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
;-----------------------------
exe1:=dir (win64 ? "\TCC-64\tcc.exe" : "\TCC-32\tcc.exe")
;-----------------------------
IfNotExist, %exe1%
{
MsgBox, 4096, Tip, Can't Find %exe1% !
return
}
;-----------------------------
add0=`n int _Flag0_%A_Now%() { return 0x11110000; } `n
add1=`n int _Flag1_%A_Now%() { return 0x11111111; } `n
add2=`n int _Flag2_%A_Now%() { return 0x11111111; } `n
add3=`n int _Flag3_%A_Now%() { return 0x11111111; } `n
s:=add0 . add1 . add2 . s . add3
;-----------------------------
FileDelete, % cpp:=dir "\5.c"
FileDelete, % obj:=dir "\5.obj"
FileDelete, % log:=dir "\5.log"
FileAppend, % StrReplace(s,"`r"), %cpp%
SplitPath, ComSpec, cmd
Loop
{
Process, Exist, %cmd%
if !(pid:=ErrorLevel)
Break
Process, Close, %pid%
Process, WaitClose, %pid%, 3
}
arg:=(win64 ? "-m64":"-m32") . " -O2"
RunWait, %ComSpec% /c ""%exe1%" %arg% -c -o "%obj%" "%cpp%" 2>"%log%""
,, Hide
IfNotExist, %obj%
{
FileRead, s, %log%
FileDelete, %cpp%
FileDelete, %log%
MsgBox, 4096, Tip, C Compile Error`n`n%s%
return
}
hex:=bin2hex(obj)
;-----------------------------
p1:=RegExMatch(hex,"i)B811111111.{0,2}?C3",r)
p2:=InStr(hex,r,0,p1+1), p3:=InStr(hex,r,0,0)
len:=p2-p1, i:=(r="B811111111C3") ? p2+len : p2+StrLen(r)
hex:=(p1 and p2) ? SubStr(hex,i,p3-p2-len) : ""
;-----------------------------
FileDelete, %cpp%
FileDelete, %obj%
FileDelete, %log%
return, hex
}
bin2hex(obj)
{
ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
SetBatchLines, % "-1" (bch:=A_BatchLines)/0
VarSetCapacity(bin,1024), VarSetCapacity(bin,0)
FileRead, bin, *c %obj%
size:=VarSetCapacity(bin), p:=&bin
VarSetCapacity(hex, (2*size+1)*(1+!!A_IsUnicode))
SetFormat, IntegerFast, % "H" (fmt:=A_FormatInteger)/0
Loop, %size%
hex.=SubStr(0x100+(*p++),-1)
SetFormat, IntegerFast, %fmt%
SetBatchLines, %bch%
ListLines, %lls%
return, hex
}
MCode(ByRef code, hex)
{
ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
SetBatchLines, % "-1" (bch:=A_BatchLines)/0
VarSetCapacity(code, len:=StrLen(hex)//2)
Loop, % len
NumPut("0x" SubStr(hex,2*A_Index-1,2),code,A_Index-1,"uchar")
DllCall("VirtualProtect","ptr",&code,"ptr",len,"uint",0x40,"ptr*",0)
SetBatchLines, %bch%
ListLines, %lls%
}
;
下面是一个AHK机器码(MCode)调用WinAPI的例子:
/****** C source code ******
#include <windows.h>
typedef int (WINAPI * _MessageBoxA)(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
typedef BOOL (WINAPI * _GetUserNameA)(
LPSTR lpBuffer,
LPDWORD pcbBuffer
);
typedef void * (WINAPI * _GetWinAPI)(char * str);
int WINAPI TestWinAPI(_GetWinAPI GetWinAPI, char * name, int * size)
{
char str1[] = "User32.dll\\MessageBoxA";
_MessageBoxA MessageBoxA = (_MessageBoxA)GetWinAPI(str1);
if (NULL == MessageBoxA)
return -1;
char str2[] = "Advapi32.dll\\GetUserNameA";
_GetUserNameA GetUserNameA = (_GetUserNameA)GetWinAPI(str2);
if (NULL == GetUserNameA)
return -2;
char text[] = "Hello World!";
char title[] = "Machine Code Call WinAPI";
MessageBoxA(0, text, title, 1);
GetUserNameA(name, size);
MessageBoxA(0, name, title, 1);
return 0;
}
*/
if (!MyFunc)
{
x32:="5557BA78410000565383EC7C8D4424268BB424900000008"
. "BBC2494000000C744242655736572C744242A33322E64C7442"
. "42E6C6C5C4DC744243265737361C74424366765426F6689542"
. "43AC644243C00890424FFD683EC0485C00F840301000089C3B"
. "841000000C744245641647661668944246E8D442456C744245"
. "A70693332C744245E2E646C6CC74424625C476574C74424665"
. "5736572C744246A4E616D65890424FFD683EC0485C089C60F8"
. "4BE0000008D6C243D8D442419C744241948656C6CC744241D6"
. "F20576FC7442421726C6421C644242500C744243D4D616368C"
. "7442441696E6520C7442445436F6465C74424492043616CC74"
. "4244D6C205769C74424516E415049C644245500C744240C010"
. "00000896C240889442404C7042400000000FFD383EC108B842"
. "498000000893C2489442404FFD683EC08C744240C010000008"
. "96C2408897C2404C7042400000000FFD331C083EC1083C47C5"
. "B5E5F5DC20C00B8FFFFFFFFEBEF8DB600000000B8FEFFFFFFE"
. "BE2909090909090909090"
x64:="4154555756534881EC9000000048B85573657233322E644"
. "8894424304889D748B86C6C5C4D65737361BA784100004889C"
. "E4D89C44889442438C74424406765426F488D4C24306689542"
. "444C644244600FFD64885C04889C30F84E200000048B841647"
. "66170693332488D4C2470488944247048B82E646C6C5C47657"
. "4488944247848B8557365724E616D654889842480000000B84"
. "10000006689842488000000FFD64885C04889C60F84A200000"
. "048B848656C6C6F20576F488D6C245041B9010000004889442"
. "42048B84D616368696E6520488D542420488944245048B8436"
. "F64652043616C4989E8488944245848B86C2057696E4150493"
. "1C9C7442428726C6421C644242C004889442460C644246800F"
. "FD34C89E24889F9FFD641B9010000004989E84889FA31C9FFD"
. "331C04881C4900000005B5E5F5D415CC30F1F440000B8FFFFF"
. "FFFEBE6660F1F840000000000B8FEFFFFFFEBD690909090909"
. "0909090"
MCode(MyFunc, A_PtrSize=8 ? x64:x32)
GetWinAPI:=RegisterCallback("GetWinAPI","Fast")
}
VarSetCapacity(str,100,0), size:=100
DllCall(&MyFunc, "Ptr",GetWinAPI, "Ptr",&str, "int*",size)
MsgBox, 1, AHK Command
, % "UserName:`t" StrGet(&str,"CP0") "`nSize:`t`t" size
return
GetWinAPI(pstr) ; 参数格式为:DLL文件名\\函数名
{
static WinAPI:=[]
if (addr:=WinAPI[ v:=StrGet(pstr,"CP0") ])
return, addr
i:=InStr(v,"\",0,0), v1:=SubStr(v,1,i-1), v2:=SubStr(v,i+1)
if !(base:=DllCall("LoadLibrary", "Str",v1, "Ptr"))
return, 0
if !(addr:=DllCall("GetProcAddress", "Ptr",base, "AStr",v2, "Ptr"))
return, 0
WinAPI[v]:=addr
return, addr
}
MCode(ByRef code, hex)
{
ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
SetBatchLines, % "-1" (bch:=A_BatchLines)/0
VarSetCapacity(code, len:=StrLen(hex)//2)
Loop, % len
NumPut("0x" SubStr(hex,2*A_Index-1,2),code,A_Index-1,"uchar")
DllCall("VirtualProtect","ptr",&code,"ptr",len,"uint",0x40,"ptr*",0)
SetBatchLines, %bch%
ListLines, %lls%
}
;
利用TCC动态运行C语言代码的简单方式:
(必须在AHK目录下安装 “\TCC-64\tcc.exe” 和 “\TCC-32\tcc.exe”)
;------------------------------------------
; Using TCC to run C code (By FeiYue)
;------------------------------------------
Goto, F1
F1::
code=
(
//////////////
char * __attribute__((stdcall)) hello(char * out) {
char str[]="Hello World!";
for (int i=0; str[i]!='\0'; i++)
out[i]=str[i];
return out;
}
//////////////
)
VarsetCapacity(str,100,0)
MsgBox, 4096,, % StrGet( DllCall(TccRun(code), "ptr",&str, "ptr"), "CP0")
return
;========== TCC Functions ==========
TccRun(s)
{
static Address:=[]
if (addr:=Address[hash:=GetHash(s)])
return, addr
if !(hex:=Tcc(s, A_PtrSize=8))
return
if !(addr:=DllCall("GlobalAlloc", "int",0, "ptr",len:=StrLen(hex)//2, "ptr"))
return
MCode(code,hex), DllCall("RtlMoveMemory", "ptr",addr, "ptr",&code, "ptr",len)
DllCall("VirtualProtect", "ptr",addr, "ptr",len, "uint",0x40, "ptr*",0)
Address[hash]:=addr
return, addr
}
GetHash(s)
{
ListLines, % "Off" (lls:=A_ListLines!=0 ? "On":"Off")/0
SetBatchLines, % "-1" (bch:=A_BatchLines)/0
hash1:=hash2:=hash3:=0, size:=VarSetCapacity(s,-1), p:=&s
Loop, % size
v:=*p++
, hash1:=(hash1*31 +v)&0xFFFFFFFF
, hash2:=(hash2*131 +v)&0xFFFFFFFF
, hash3:=(hash3*1313+v)&0xFFFFFFFF
SetBatchLines, %bch%
ListLines, %lls%
return, hash1 "-" hash2 "-" hash3
}
Tcc(s, win64=0)
{
dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
;-----------------------------
exe1:=dir (win64 ? "\TCC-64\tcc.exe" : "\TCC-32\tcc.exe")
;-----------------------------
IfNotExist, %exe1%
{
MsgBox, 4096, Tip, Can't Find %exe1% !
return
}
;-----------------------------
add0=`n int _Flag0_%A_Now%() { return 0x11110000; } `n
add1=`n int _Flag1_%A_Now%() { return 0x11111111; } `n
add2=`n int _Flag2_%A_Now%() { return 0x11111111; } `n
add3=`n int _Flag3_%A_Now%() { return 0x11111111; } `n
s:=add0 . add1 . add2 . s . add3
;-----------------------------
FileDelete, % cpp:=dir "\5.c"
FileDelete, % obj:=dir "\5.obj"
FileDelete, % log:=dir "\5.log"
FileAppend, % StrReplace(s,"`r"), %cpp%
SplitPath, ComSpec, cmd
Loop
{
Process, Exist, %cmd%
if !(pid:=ErrorLevel)
Break
Process, Close, %pid%
Process, WaitClose, %pid%, 3
}
arg:=(win64 ? "-m64":"-m32") . " -O2"
RunWait, %ComSpec% /c ""%exe1%" %arg% -c -o "%obj%" "%cpp%" 2>"%log%""
,, Hide
IfNotExist, %obj%
{
FileRead, s, %log%
FileDelete, %cpp%
FileDelete, %log%
MsgBox, 4096, Tip, C Compile Error`n`n%s%
return
}
hex:=bin2hex(obj)
;-----------------------------
p1:=RegExMatch(hex,"i)B811111111.{0,2}?C3",r)
p2:=InStr(hex,r,0,p1+1), p3:=InStr(hex,r,0,0)
len:=p2-p1, i:=(r="B811111111C3") ? p2+len : p2+StrLen(r)
hex:=(p1 and p2) ? SubStr(hex,i,p3-p2-len) : ""
;-----------------------------
FileDelete, %cpp%
FileDelete, %obj%
FileDelete, %log%
return, hex
}
bin2hex(obj)
{
ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
SetBatchLines, % "-1" (bch:=A_BatchLines)/0
VarSetCapacity(bin,1024), VarSetCapacity(bin,0)
FileRead, bin, *c %obj%
size:=VarSetCapacity(bin), p:=&bin
VarSetCapacity(hex, (2*size+1)*(1+!!A_IsUnicode))
SetFormat, IntegerFast, % "H" (fmt:=A_FormatInteger)/0
Loop, %size%
hex.=SubStr(0x100+(*p++),-1)
SetFormat, IntegerFast, %fmt%
SetBatchLines, %bch%
ListLines, %lls%
return, hex
}
MCode(ByRef code, hex)
{
ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
SetBatchLines, % "-1" (bch:=A_BatchLines)/0
VarSetCapacity(code, len:=StrLen(hex)//2)
Loop, % len
NumPut("0x" SubStr(hex,2*A_Index-1,2),code,A_Index-1,"uchar")
DllCall("VirtualProtect","ptr",&code,"ptr",len,"uint",0x40,"ptr*",0)
SetBatchLines, %bch%
ListLines, %lls%
}
;