;===========================================
;   【AHK机器码生成器】 v2.5  By FeiYue
;
;   使用方法:
;
;   1、下载安装【TDM-GCC】的64位版到D盘的TDM-GCC-64目录,下载网址为:
;      https://sourceforge.net/projects/tdm-gcc/files/latest/download
;
;   2、下载安装【TCC】的32位和64位版到AHK的TCC-32和TCC-64目录,下载网址为:
;      https://bellard.org/tcc/
;
;   3、选择C代码后,按【 Alt+C 】热键生成 GCC 编译的机器码,
;      或者按【 Ctrl+Alt+C 】热键生成 TCC 编译的机器码
;
;===========================================

; https://www.autohotkey.com/boards/viewtopic.php?t=18405

!c::    ; 选择C代码后用 GCC 编译

^!c::   ; 选择C代码后用 TCC 编译

ClipSaved:=ClipboardAll
Clipboard=
Send {Ctrl Down}c{Ctrl Up}
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, s%i%:="`r`n    " (i ? "x64":"x32") ":="""""
  . RegExReplace(Tcc(s,i,A_ThisLabel="!c"), ".{1,64}", "`r`n    . ""$0""")
}
MsgBox, 4096, MCode has been generated! (32 + 64), % Clipboard:=s0 . s1
  . "`r`n    MCode(MyFunc, A_PtrSize=8 ? x64:x32)"
s:=s0:=s1:=""
return

Tcc(s, win64=0, gcc=0, add=0)
{
  dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
  if (gcc=1)
    exe1:="D:\TDM-GCC-64\bin\gcc.exe"
  else
    exe1:=dir (win64 ? "\TCC-64":"\TCC-32") "\tcc.exe"
  IfNotExist, %exe1%
  {
    MsgBox, 4096, Tip, Can t Find %exe1% !
    return
  }
  if (add=1)
  {
    Loop, 4
      s%A_Index%:="int _add" A_Index "_() { return 0x11111111; }"
    s:=s1 "`n" s2 "`n" s3 "`n" s "`n" s4 "`n"
  }
  dir:=A_Temp
  FileDelete, % cpp:=dir "\~5.c"
  FileDelete, % obj:=dir "\~5.obj"
  FileDelete, % log:=dir "\~5.log"
  FileAppend, % StrReplace(s,"`r"), %cpp%
  killcmd(1)
  arg:=(win64 ? " -m64 ":" -m32 ")  " -O2 "
  RunWait, %ComSpec% /c ""%exe1%" %arg%
    -c -o "%obj%" "%cpp%" 2>"%log%"",, Hide
  killcmd(0)
  hex:=(add=1) ? bin2hex(obj) : obj2hex(obj)
  FileRead, s, %log%
  FileDelete, %cpp%
  FileDelete, %obj%
  FileDelete, %log%
  if StrLen(hex)<2
  {
    MsgBox, 4096, Tip, C Compile Error`n`n%s%
    return
  }
  if (add=1)
  {
    p1:=RegExMatch(hex, "i)B811111111.{0,8}?C3", r)
    p2:=InStr(hex,r,0,p1+1), p3:=InStr(hex,r,0,p2+1)
    p4:=InStr(hex,r,0,0), len:=p3-p2, i:=0
    Loop, % (len-StrLen(r))//2
      if !(SubStr(hex,p1-2-i,2)=SubStr(hex,p3-2-i,2)
      && SubStr(hex,p1-2-i,2)=SubStr(hex,p4-2-i,2) && (i+=2))
        Break
    if (p1 && p2 && p3)
      hex:=SubStr(hex, p3+len-i, p4-p3-len)
  }
  return hex
}

killcmd(f=0)
{
  SplitPath, ComSpec, cmd
  Loop
  {
    Process, Exist, %cmd%
    if !(pid:=ErrorLevel)
      Break
    Process, Close, %pid%
    Process, WaitClose, %pid%, 3
  }
  SetTimer, killcmd, % f ? 5000 : "Off"
}

bin2hex(obj, addr=0, size=0)
{
  if (addr=0)
  {
    if !(r:=FileExist(obj)) or InStr(r,"D")
      return
    FileGetSize, size, %obj%
    FileRead, bin, *c %obj%
    addr:=&bin
  }
  ListLines, % (lls:=A_ListLines=0?"Off":"On")?"Off":"Off"
  SetBatchLines, % (bch:=A_BatchLines)?"-1":"-1"
  SetFormat, IntegerFast, % (fmt:=A_FormatInteger)?"H":"H"
  VarSetCapacity(hex, (2*size+1)*(1+!!A_IsUnicode))
  Loop, %size%
    hex.=SubStr(0x100+(*addr++),-1)
  SetFormat, IntegerFast, %fmt%
  SetBatchLines, %bch%
  ListLines, %lls%
  return hex
}

obj2hex(obj)
{
  if !(r:=FileExist(obj)) or InStr(r,"D")
    return
  FileGetSize, size, %obj%
  FileRead, bin, *c %obj%
  p:=&bin
  if !(NumGet(p+0,"uchar")=0x7f && StrGet(p+1,3,"CP0")="ELF")
  {
    if (StrGet(p,2,"CP0")="MZ")
    && (StrGet(p+NumGet(p+0x3C,"uint"),4,"CP0")="PE")
      return
    usOptHdrSZ := NumGet(p+0, 16, "ushort")
    Loop % usNumSec := NumGet(p+0, 2, "ushort")
    {
      sh := 20+usOptHdrSZ+(A_Index-1)*40
      if (sh>size || A_Index>100)
        return
      sh_flags := NumGet(p+0, sh+36, "uint")
      name:=StrGet(p+sh, 8, "CP0")
      if (name=".text") && (sh_flags & 0x20)
      {
        sh_offset := NumGet(p+0, sh+20, "uint")
        sh_size := NumGet(p+0, sh+16, "uint")
        return bin2hex("", p+sh_offset, sh_size)
      }
    }
    return
  }
  x64:=(EI_CLASS := NumGet(p+0, 4, "char"))=2
  ptr:=(x64 ? "uint64" : "uint")
  e_ehsize:=NumGet(p+0, (x64?52:40), "ushort")
  if (e_ehsize!=(x64?64:52))
    return
  e_shoff := NumGet(p+0, (x64?40:32), ptr)
  e_shentsize := NumGet(p+0, (x64?58:46), "ushort")
  e_shnum := NumGet(p+0, (x64?60:48), "ushort")
  e_shstrndx := NumGet(p+0, (x64?62:50), "ushort")
  sh := e_shoff+e_shstrndx*e_shentsize
  pstr := NumGet(p+0, sh+(x64?24:16), ptr) + p
  Loop % e_shnum
  {
    sh := e_shoff+(A_Index-1)*e_shentsize
    if (sh>size || A_Index>100)
      return
    sh_flags := NumGet(p+0, sh+8, ptr)
    sh_name := NumGet(p+0, sh+0, "uint")
    name := StrGet(pstr+sh_name, 8, "CP0")
    if (name=".text") && (sh_flags & 0x4)
    {
      sh_offset := NumGet(p+0, sh+(x64?24:16), ptr)
      sh_size := NumGet(p+0, sh+(x64?32:20), ptr)
      return bin2hex("", p+sh_offset, sh_size)
    }
  }
}

MCode(ByRef code, hex)
{
  ListLines, % (lls:=A_ListLines=0?"Off":"On")?"Off":"Off"
  SetBatchLines, % (bch:=A_BatchLines)?"-1":"-1"
  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%
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。