UWSCスクリプトとネイティブコードのキメラ
難読化、といえば、こういう方法もある、という紹介。
ロジックの一部を、ネイティブコードに載せて、わかりにくくする。
とりあえず、0〜9のループを隠蔽してみた。
0〜9にコマンドを割り当てて、ループでない順番に実行させれば、わかりにくいですね。
ループを隠蔽したスクリプト
Complex.uws
OPTION EXPLICIT IFB GET_UWSC_NAME = "Complex.uws" THEN //for(UINT i = 0; i < 10; i++) { // p->data = i; // p->SetEvent(p->hEvent); // p->WaitForSingleObject(p->hEventSync, INFINITE); //} DIM addr = Asm.Set("VYvsg+wIi0UIiUX8x0X4AAAAAOsJi034g8EBiU34g334CnMqi1X8i0X4iUIQi038i1EIUotF/IsI/9Fq/4tV/ItCDFCLTfyLUQT/0uvHM8CL5V3CBADM") DIM paraSize = 20, para = Asm.Alloc(paraSize), i = 0 IFB addr > 0 AND para > 0 THEN i = i + Asm.SetDword(para + i, Asm.GetProcAddress(Asm.hK32, "SetEvent")) i = i + Asm.SetDword(para + i, Asm.GetProcAddress(Asm.hK32, "WaitForSingleObject")) DEF_DLL CreateEventA(DWORD,BOOL,BOOL,DWORD): DWORD: kernel32 DIM hEvent = CreateEventA(0, FALSE, FALSE, 0) DIM hEventSync = CreateEventA(0, FALSE, FALSE, 0) i = i + Asm.SetDword(para + i, hEvent) i = i + Asm.SetDword(para + i, hEventSync) //Asm.Dump(para, paraSize) // UWSC側実行スクリプトを起動する THREAD ProcMain(hEvent, hEventSync, para + i) // コントロール用ネイティブスレッドを起動する // UWSCのメインスレッドが止まるとサブも止まるみたい DIM hThread = Asm.Run(addr, para, i, -1), res = 258 WHILE res = 258 res = Asm.WaitForSingleObject(hThread, 10) WEND Asm.CloseHandle(hThread) // 解放 Asm.Free(para) Asm.Free(addr) Asm.CloseHandle(hEvent) Asm.CloseHandle(hEventSync) ENDIF ENDIF PROCEDURE ProcMain(hEvent, hEventSync, p) DEF_DLL SetEvent(DWORD): bool: kernel32 DIM para = 0 WHILE para < 9 Asm.WaitForSingleObject(hEvent, $FFFFFFFF) para = Asm.GetDword(p) PRINT "Para:" + para SetEvent(hEventSync) WEND FEND // このAsmモジュールは、GetDword追加型 MODULE Asm DEF_DLL GetLastError(): DWORD: kernel32 DEF_DLL VirtualAlloc(DWORD, DWORD, DWORD, DWORD): DWORD: kernel32 DEF_DLL VirtualFree(DWORD, DWORD, DWORD): bool: kernel32 DEF_DLL GetModuleHandleA(string): DWORD: kernel32 DEF_DLL GetProcAddress(DWORD, string): DWORD: kernel32 DEF_DLL CreateThread(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD): DWORD: kernel32 DEF_DLL WaitForSingleObject(DWORD, DWORD): DWORD: kernel32 DEF_DLL CloseHandle(DWORD): bool: kernel32 DEF_DLL GetExitCodeThread(DWORD, var DWORD): bool: kernel32 PUBLIC hK32 PUBLIC hU32 PROCEDURE Asm hk32 = GetModuleHandleA("kernel32") hU32 = GetModuleHandleA("user32") FEND FUNCTION Set(code) DIM dom = CreateOleObj("Microsoft.XMLDOM") DIM binMan = dom.createElement("tmp") binMan.dataType = "bin.base64" binMan.text = code DIM i = LENGTH(code), size = i * 3 / 4 IFB i > 3 THEN IF COPY(code, i-1, 1) = "=" THEN size = size - 1 IF COPY(code, i, 1) = "=" THEN size = size - 1 ENDIF DIM data[size-1], b = binMan.nodeTypedValue FOR i = 0 TO size - 1 data[i] = b[i] NEXT RESULT = VirtualAlloc(0, size, $1000, $40) IF RESULT THEN SetByte(RESULT, data) FEND FUNCTION Alloc(size) RESULT = VirtualAlloc(0, size, $1000, $4) FEND FUNCTION Free(addr) RESULT = VirtualFree(addr, 0, $8000) FEND // 戻りはtypeによって異なる // type=0 : スレッド終了コード // type=1 : スレッド終了コード取得失敗エラーコード // type=258 : スレッドハンドル // type=他 : その他エラーコード FUNCTION Run(addr, para, var type, timeout=$7FFFFFFF) DIM hThread = CreateThread(0, 0, addr, para, 0, 0), res = 0 RESULT = GetLastError() type = 258 IF timeout >= 0 THEN type = WaitForSingleObject(hThread, timeout) SELECT type CASE 0 IFB GetExitCodeThread(hThread, res) THEN RESULT = res ELSE type = 1 RESULT = GetLastError() ENDIF CloseHandle(hThread) CASE 258 RESULT = hThread SELEND FEND FUNCTION SetByte(p, data[]) DEF_DLL RtlMoveMemory(DWORD, BYTE[], DWORD): kernel32 RESULT = LENGTH(data) RtlMoveMemory(p, data, RESULT) FEND FUNCTION SetDword(p, data) DEF_DLL RtlMoveMemory(DWORD, var DWORD, DWORD): kernel32 RESULT = 4 RtlMoveMemory(p, data, RESULT) FEND FUNCTION SetString(p, data) DEF_DLL RtlMoveMemory(DWORD, string, DWORD): kernel32 RESULT = LENGTHB(data) RtlMoveMemory(p, data, RESULT) FEND FUNCTION GetDword(p) DEF_DLL RtlMoveMemory(var DWORD, DWORD, DWORD): kernel32 RESULT = 0 RtlMoveMemory(RESULT, p, 4) FEND PROCEDURE Dump(addr, size) DEF_DLL RtlMoveMemory(BYTE[], DWORD, DWORD): kernel32 DIM data[size], i, buf = "", bufa = "" RtlMoveMemory(data, addr, size) FOR i = 0 TO size - 1 buf = buf + FORMAT(data[i], 3, -1) IFB data[i] >= $20 AND data[i] < $7F THEN bufa = bufa + CHR(data[i]) ELSE bufa = bufa + "." ENDIF IFB i MOD 16 = 15 THEN PRINT buf + " " + bufa buf = "" bufa = "" ENDIF NEXT IF LENGTH(buf) THEN PRINT buf + FORMAT(" ", 49 - LENGTH(buf)) + bufa FEND ENDMODULE
、、、ま、ネイティブコードが書ける人なら、
ネイティブコードで行えば良いんですけどね、、、。
いや、でも、いろいろ面倒だからUWSCを使うわけで、、、。
ま、こんなキメラも作れます、ということ。