2ちゃんねる ■掲示板に戻る■ 全部 1- 最新50    

■ このスレッドは過去ログ倉庫に格納されています

アセンブリや機械語を解析して楽しむスレ

1 :デフォルトの名無しさん:2021/06/19(土) 17:16:50.94 ID:KpP01EPy.net
5ちゃんねるの総力を挙げて、人力でアセンブリや機械語を逆コンパイルするスレッドです。コード解析の達人やヒマ人の皆様、ご協力下さい。

===依頼テンプレここから===
【依頼の目的と内容説明】ここに目的と説明を書く
【プロセッサの種類】x86/x64/ARM/JVM など
【OSの種類】Windows/Linux/Mac/Android/iOS など
【言語】C/C++/Java/C# など
【報酬金額と送金方法】報酬なし/銀行振込/WebMoney など
【アセンブリまたは機械語】以下にアセンブリまたは機械語を記載
===依頼テンプレここまで===

依頼は一度に1関数までとします。あまりにも長いコードは人力では逆コンパイルできません。常識の範囲でご利用ください。

2 :デフォルトの名無しさん:2021/06/19(土) 17:35:44.71 ID:KpP01EPy.net
【依頼の目的と内容説明】知恵試し
【プロセッサの種類】x86
【OSの種類】Windows
【言語】C/C++
【報酬金額と送金方法】報酬なし
【アセンブリまたは機械語】
LC0:
__.ascii "hello\0"
__.text
__.p2align 4
__.globl _hello
__.def _hello; .scl 2; .type 32; .endef
_hello:
LFB126:
__.cfi_startproc
__subl $28, %esp
__.cfi_def_cfa_offset 32
__movl $64, 12(%esp)
__movl $0, 8(%esp)
__movl $LC0, 4(%esp)
__movl $0, (%esp)
__call *__imp__MessageBoxA@16
__.cfi_def_cfa_offset 16
__subl $16, %esp
__.cfi_def_cfa_offset 32
__addl $28, %esp
__.cfi_def_cfa_offset 4
__ret
__.cfi_endproc

3 :デフォルトの名無しさん:2021/06/19(土) 19:13:37.49 ID:Obm1tdWY.net
関連スレ

機械語なら俺に質問しろ!その2
https://mevius.5ch.net/test/read.cgi/tech/1356735624/

4 :デフォルトの名無しさん:2021/06/19(土) 19:14:20.22 ID:Obm1tdWY.net
逆アセンブラ、解析 [無断転載禁止]c2ch.net
https://mevius.5ch.net/test/read.cgi/tech/1498686597/

5 :デフォルトの名無しさん:2021/06/19(土) 19:14:49.34 ID:Obm1tdWY.net
アセンブラ 13
https://mevius.5ch.net/test/read.cgi/tech/1314512680/

6 :デフォルトの名無しさん:2021/06/19(土) 20:23:58.66 ID:Obm1tdWY.net
>>2
#include <windows.h>
int hello(void)
{
return MessageBoxA(NULL, "hello", NULL, MB_ICONINFORMATION);
}

7 :デフォルトの名無しさん:2021/06/19(土) 20:42:09.84 ID:KpP01EPy.net
>>6
すげー、正解www

どうやったらアセンブリ読めるんだ? 教えてくれよ

8 :デフォルトの名無しさん:2021/06/19(土) 21:51:43.98 ID:Obm1tdWY.net
>>7
アセンブラや解析の本を読んでみなよ

初心者なら
https://ja.m.wikibooks.org/wiki/X86%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9/GAS%E3%81%A7%E3%81%AE%E6%96%87%E6%B3%95
この辺から読み始めるといいよ。

9 :デフォルトの名無しさん:2021/06/19(土) 23:37:15.06 ID:/D3aIkOV.net
スレ立てたの素人かよ

10 :デフォルトの名無しさん:2021/06/20(日) 14:20:56.65 ID:dQPhad/Q.net
【依頼の目的と内容説明】 shell32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
proc Func7C903F7F@16 Label_7C903F7F
Label_7C8FAE6A:
7C8FAE6A: cmp dword [ebp+0x10], 0x0 # jump_from : 7C903F91
7C8FAE6E: push dword [ebp+0x14]
7C8FAE71: jz Label_7C8FAE84
7C8FAE73: push dword [ebp+0xc]
7C8FAE76: push dword [ebp+0x8]
7C8FAE79: call shlwapi.dll!6
7C8FAE7F: jmp Label_7C903F99
Label_7C8FAE84:
7C8FAE84: push dword [ebp+0x8] # jump_from : 7C8FAE71
7C8FAE87: call shlwapi.dll!4
7C8FAE8D: jmp Label_7C903F99
Label_7C903F7F:
7C903F7F: mov edi, edi
7C903F81: push ebp
7C903F82: mov ebp, esp
7C903F84: push dword [ebp+0x8]
7C903F87: call shlwapi.dll!PathFindExtensionW
7C903F8D: cmp word [eax], 0x0
7C903F91: jz Label_7C8FAE6A
7C903F97: xor eax, eax
Label_7C903F99:
7C903F99: pop ebp # jump_from : 7C8FAE7F 7C8FAE8D
7C903F9A: ret 0x10
end proc
shlwapi.dll!6は3引数の関数で、shlwapi.dll!4は2引数の関数で、PathFindExtensionWは1引数の関数です。
よろしくお願いいたします。

11 :デフォルトの名無しさん:2021/06/20(日) 18:43:24.30 ID:dQPhad/Q.net
>>10
最初の項目を1番目とする。正の向きを下向きまたは右向きとする。
問題の関数はFunc7C903F7F関数である。Func7C903F7Fは仮の名前で7C903F7Fが関数の仮想アドレスを表す。
Func7C903F7Fの入り口は、7C903F7Fである。出口は7C903F9A: ret 0x10とあるので、
Func7C903F7F関数は__stdcallであり 16バイトの引数リストを持つ。
おそらく32ビット(4バイト)の引数が4個ある。任意の関数「f」のi番目の実引数を「f.#i」と表すことにする。
最初に入口の7C903F7Fに入る。
7C903F7F: mov edi, edi
これは何もしない。
7C903F81: push ebp
7C903F82: mov ebp, esp
これはスタックフレームを確立する。すると
ESP=EBP=[(old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
となる。よって[ebp+0x8]はFunc7C903F7F.#1である。さらに
7C903F84: push dword [ebp+0x8]
7C903F87: call shlwapi.dll!PathFindExtensionW
ここで、Func7C903F7F.#1をプッシュしてPathFindExtensionWを呼び出す。
PathFindExtensionWの呼び出し規約は__stdcallであるから、C言語風に書くと
eax = PathFindExtensionW(Func7C903F7F.#1);
となる。呼び出した後は、プッシュしたFunc7C903F7F.#1はスタックから解放される。
7C903F8D: cmp word [eax], 0x0
7C903F91: jz Label_7C8FAE6A
これはif (*(WORD *)eax == 0) goto Label_7C8FAE6A;と解釈される。このeaxはPathFindExtensionWの戻り値である。
*(WORD *)eaxの値によって次の(a.1)か(a.2)に分岐する。
(a.1) *(WORD *)eaxが非ゼロの場合。
7C903F97: xor eax, eax
ここでeaxはクリアされてスタックフレームが破棄されてFunc7C903F7F関数はゼロを返す。
(a.2) *(WORD *)eaxがゼロの場合。Label_7C8FAE6Aに飛ぶ。
7C8FAE6A: cmp dword [ebp+0x10], 0x0 # jump_from : 7C903F91
...(続く)...

12 :デフォルトの名無しさん:2021/06/20(日) 18:44:37.17 ID:dQPhad/Q.net
...(続き)...
ここでスタックは
ESP=EBP=[(old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
であったから、[ebp+0x10]は、Func7C903F7F.#3である。
Func7C903F7F.#3とゼロを比較して結果をZeroFlagに格納する。
7C8FAE6E: push dword [ebp+0x14]
ここで[ebp+0x14]は、Func7C903F7F.#4であった。Func7C903F7F.#4をプッシュすると、
ESP=[Func7C903F7F.#4, (old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
EBP=[(old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
となる。次に進む。
7C8FAE71: jz Label_7C8FAE84
これは
if (ZeroFlag) goto Label_7C8FAE84;
となる。すなわちZeroFlagによって次の(b.1)か(b.2)に分岐する。
(b.1) ZeroFlagが偽の場合。
7C8FAE73: push dword [ebp+0xc]
ここで[ebp+0xc]は、Func7C903F7F.#2であった。Func7C903F7F.#2がプッシュされて
ESP=[Func7C903F7F.#2, Func7C903F7F.#4, (old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
EBP=[(old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
となる。さらに
7C8FAE76: push dword [ebp+0x8]
ここで[ebp+0x8]は、Func7C903F7F.#1であった。Func7C903F7F.#1がプッシュされて
ESP=[Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#4, (old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
EBP=[(old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
となる。
7C8FAE79: call shlwapi.dll!6
これはC風に書くとeax = shlwapi.dll!6(Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#4);となる。さらに
7C8FAE7F: jmp Label_7C903F99
でLabel_7C903F99に飛び、スタックフレームが破棄されて、Func7C903F7Fは戻り値eaxを返す。
(b.2) ZeroFlagが真の場合。Label_7C8FAE84に飛ぶ。
...(続く)...

13 :デフォルトの名無しさん:2021/06/20(日) 18:46:06.04 ID:dQPhad/Q.net
...(続き)...
7C8FAE84: push dword [ebp+0x8]
ここで[ebp+0x8]は、Func7C903F7F.#1であった。Func7C903F7F.#1がプッシュされて、
ESP=[Func7C903F7F.#1, Func7C903F7F.#4, (old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
EBP=[(old EBP), (復帰アドレス), Func7C903F7F.#1, Func7C903F7F.#2, Func7C903F7F.#3, Func7C903F7F.#4]
となる。さらに
7C8FAE87: call shlwapi.dll!4
これはC風に書くとeax = shlwapi.dll!4(Func7C903F7F.#1, Func7C903F7F.#4);となる。
7C8FAE8D: jmp Label_7C903F99
これでLabel_7C903F99に飛び、スタックフレームが破棄されてFunc7C903F7Fは戻り値eaxを返す。

以上をまとめると

unknown Func7C903F7F(unknown p1, unknown p2, unknown p3, unknown p4)
{
if (*(WORD *)PathFindExtensionW(p1) != 0)
return 0;
if (!p3)
return shlwapi.dll!4(p1, p4);
else
return shlwapi.dll!6(p1, p2, p4);
}

p1はPathFindExtensionWの引数なので、型はLPCWSTRである。p3は使われ方からBOOL型であると推測される。
ReactOSのソースdll/win32/shlwapi/shlwapi.specを見ると、
shlwapi.dll!4は、PathFileExistsDefExtWであり、shlwapi.dll!6は、PathFindOnPathExWである。
...(続く)...

14 :デフォルトの名無しさん:2021/06/20(日) 18:47:21.92 ID:dQPhad/Q.net
...(続き)...
各関数のプロトタイプを確認し、整理すると

BOOL Func7C903F7F(LPCWSTR path, LPCWSTR *dirs, BOOL flag, DWORD dwWhich)
{
if (*PathFindExtensionW(path) != 0)
return FALSE;
if (!flag)
return PathFileExistsDefExtW(path, dwWhich);
else
return PathFindOnPathExW(path, dirs, dwWhich);
}

となり、これで逆コンパイルが完了する。     □

15 :デフォルトの名無しさん:2021/06/20(日) 19:11:08.28 ID:dQPhad/Q.net
【依頼の目的と内容説明】shell32.dllの解析 【プロセッサの種類】x86 【OSの種類】Win Server 2003 【言語】C/C++ 【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
proc Func7C8FF2D3@4 Label_7C8FF2D3
Label_7C8FF2D3:
7C8FF2D3: mov edi, edi
7C8FF2D5: push ebp
7C8FF2D6: mov ebp, esp
7C8FF2D8: push esi
7C8FF2D9: mov esi, [ebp+0x8]
7C8FF2DC: push esi
7C8FF2DD: call shlwapi.dll!PathIsUNCW@4
7C8FF2E2: test eax, eax
7C8FF2E4: jz Label_7C8FF3FC
Label_7C8FF2EA:
7C8FF2EA: xor eax, eax # jump_from : 7C8FF40C
7C8FF2EC: inc eax
Label_7C8FF2ED:
7C8FF2ED: pop esi # jump_from : 7C8FF414
7C8FF2EE: pop ebp
7C8FF2EF: ret 0x4
Label_7C8FF3FC:
7C8FF3FC: push esi # jump_from : 7C8FF2E4
7C8FF3FD: call shlwapi.dll!PathGetDriveNumberW@4
7C8FF402: cmp eax, 0xffffffff
7C8FF405: jz Label_7C8FF412
7C8FF407: cmp word [esi+0x4], 0x5c
7C8FF40C: jz Label_7C8FF2EA
Label_7C8FF412:
7C8FF412: xor eax, eax # jump_from : 7C8FF405
7C8FF414: jmp Label_7C8FF2ED
end proc
よろしくお願いいたします。

16 :デフォルトの名無しさん:2021/06/20(日) 20:40:13.59 ID:dQPhad/Q.net
>>15
関数Func7C8FF2D3の入口7C8FF2D3より入る。
「7C8FF2D3: mov edi, edi」は何もしない。
7C8FF2D5: push ebp
7C8FF2D6: mov ebp, esp
スタックフレームを確立する。
7C8FF2D8: push esi
esiの値をスタックに保存する。
ESP=[(old ESI), (old EBP), (復帰アドレス), Func7C8FF2D3.#1],
EBP=[(old EBP), (復帰アドレス), Func7C8FF2D3.#1].
ここで、[ebp+0x8]は、Func7C8FF2D3.#1である。
7C8FF2D9: mov esi, [ebp+0x8]
esiにFunc7C8FF2D3.#1を代入する。
7C8FF2DC: push esi
7C8FF2DD: call shlwapi.dll!PathIsUNCW@4
esi=Func7C8FF2D3.#1をプッシュしてPathIsUNCWを呼ぶ。
C風に書くとeax = PathIsUNCW(Func7C8FF2D3.#1);
プッシュしたFunc7C8FF2D3.#1は呼び出し完了後、解放される。
7C8FF2E2: test eax, eax
7C8FF2E4: jz Label_7C8FF3FC
これはif (!eax) goto Label_7C8FF3FC;と解釈される。よって(c.1)と(c.2)に分岐する。
(c.1) eaxが非ゼロの場合。
7C8FF2EA: xor eax, eax
7C8FF2EC: inc eax
これはeaxに1を代入することに等しい。さらに
7C8FF2ED: pop esi
7C8FF2EE: pop ebp
7C8FF2EF: ret 0x4
ESIを復元し、スタックフレームを解放してeax=1を返す。
...(続く)...

17 :デフォルトの名無しさん:2021/06/20(日) 20:41:31.44 ID:dQPhad/Q.net
...(続き)...
(c.2) eax非ゼロの場合。Label_7C8FF3FCに飛ぶ。
7C8FF3FC: push esi
7C8FF3FD: call shlwapi.dll!PathGetDriveNumberW@4
esi=Func7C8FF2D3.#1をプッシュしてPathGetDriveNumberWを呼ぶ。
これはeax = PathGetDriveNumberW(Func7C8FF2D3.#1);と解釈される。
7C8FF402: cmp eax, 0xffffffff
7C8FF405: jz Label_7C8FF412
eax、つまりPathGetDriveNumberWの戻り値が-1であればLabel_7C8FF412に飛ぶ。
これはif (eax == -1) goto Label_7C8FF412; と解釈される。
7C8FF407: cmp word [esi+0x4], 0x5c
7C8FF40C: jz Label_7C8FF2EA
これはif (((const WORD *)ESI)[2] == 0x5c) goto Label_7C8FF2EA;と解釈される。
7C8FF412: xor eax, eax
7C8FF414: jmp Label_7C8FF2ED
これはeaxをゼロクリアしてLabel_7C8FF2EDに飛ぶ。
...(続く)...

18 :デフォルトの名無しさん:2021/06/20(日) 20:42:30.48 ID:dQPhad/Q.net
...(続き)... まとめると
unknown Func7C8FF2D3(unknown p1)
{
eax = PathIsUNCW(p1);
if (eax)
{
Label_7C8FF2EA:
eax = 1;
Label_7C8FF2ED:
return eax;
}
eax = PathGetDriveNumberW(p1);
if (eax == -1)
goto Label_7C8FF412;
if (((const WORD *)p1)[2] == 0x5C)
goto Label_7C8FF2EA;
Label_7C8FF412:
eax = 0;
goto Label_7C8FF2ED;
}

整理すると
BOOL Func7C8FF2D3(LPCWSTR path)
{
if (PathIsUNCW(path))
return TRUE;
if (PathGetDriveNumberW(path) == -1)
return FALSE;
return (path[2] == L'\\');
}
となる。逆コンパイル完了。 □

19 :デフォルトの名無しさん:2021/06/20(日) 22:50:23.97 ID:b3Yj6C5d.net
>>18
もっと簡略化できるよ。
BOOL Func7C8FF2D3(LPCWSTR path)
{
return PathIsUNCW(path) || (PathGetDriveNumberW(path) != -1 && path[2] == L'\\');
}

20 :デフォルトの名無しさん:2021/06/21(月) 07:48:39.30 ID:6C6uvD3w.net
【依頼の目的と内容説明】 shell32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
proc Func7C9A5238@4 Label_7C9A5238
Label_7C9A5238:
7C9A5238: mov edi, edi
7C9A523A: push ebp
7C9A523B: mov ebp, esp
7C9A523D: sub esp, 0x20c
7C9A5243: mov eax, [0x7cae9764]
7C9A5248: push edi
7C9A5249: mov edi, [ebp+0x8]
7C9A524C: test edi, edi
7C9A524E: mov [ebp-0x4], eax
7C9A5251: jnz Label_7C9A5257
7C9A5253: xor eax, eax
7C9A5255: jmp Label_7C9A528D
Label_7C9A5257:
7C9A5257: push esi # jump_from : 7C9A5251
7C9A5258: lea eax, [ebp-0x20c]
7C9A525E: push eax
7C9A525F: mov esi, 0x104
7C9A5264: push esi
7C9A5265: call kernel32.dll!GetCurrentDirectoryW
7C9A526B: test eax, eax
7C9A526D: jz Label_7C9A528A
7C9A526F: cmp eax, esi
7C9A5271: ja Label_7C9A528A
7C9A5273: push edi
...(続く)...

21 :デフォルトの名無しさん:2021/06/21(月) 07:58:16.17 ID:6C6uvD3w.net
...(続き)...
7C9A5274: lea eax, [ebp-0x20c]
7C9A527A: push eax
7C9A527B: push edi
7C9A527C: call shlwapi.dll!PathCombineW
7C9A5282: neg eax
7C9A5284: sbb eax, eax
7C9A5286: neg eax
7C9A5288: jmp Label_7C9A528C
Label_7C9A528A:
7C9A528A: xor eax, eax # jump_from : 7C9A526D 7C9A5271
Label_7C9A528C:
7C9A528C: pop esi # jump_from : 7C9A5288
Label_7C9A528D:
7C9A528D: mov ecx, [ebp-0x4] # jump_from : 7C9A5255
7C9A5290: pop edi
7C9A5291: call Func7C92EC80
7C9A5296: leave
7C9A5297: ret 0x4
end proc

よろしくお願いいたします。

22 :デフォルトの名無しさん:2021/06/21(月) 09:21:15.08 ID:6C6uvD3w.net
>>20-21

INT Func7C9A5238(LPWSTR p1)
{
WCHAR path1[MAX_PATH];
DWORD cch, v1 = *(DWORD*)0x7cae9764;
BOOL ret = FALSE;
if (p1 == NULL)
goto Quit;
cch = GetCurrentDirectoryW(MAX_PATH, path1);
if (!cch || cch > MAX_PATH)
goto Quit;
if (PathCombineW(p1, path1, p1) != NULL)
ret = TRUE;
Quit:
ecx = v1;
Func7C92EC80(...); // 引数はわからない。ecxの値をチェックしているようだ。
return ret;
}



23 :デフォルトの名無しさん:2021/06/21(月) 09:34:40.87 ID:6C6uvD3w.net
【依頼の目的と内容説明】 shell32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
proc Func7C92C7B9@12 Label_7C92C7B9
Label_7C9138BF:
7C9138BF: dec edx # jump_from : 7C92C7E9
7C9138C0: dec edx
7C9138C1: mov eax, 0x8007007a
7C9138C6: jmp Label_7C92C7EF
Label_7C92C7B9:
7C92C7B9: mov edi, edi
7C92C7BB: push ebp
7C92C7BC: mov ebp, esp
7C92C7BE: xor eax, eax
7C92C7C0: cmp [ebp+0xc], eax
7C92C7C3: jz Label_7C98E437
7C92C7C9: mov edx, [ebp+0x8]
7C92C7CC: push esi
7C92C7CD: mov esi, [ebp+0x10]
Label_7C92C7D0:
7C92C7D0: mov cx, [esi] # jump_from : 7C92C7E2
7C92C7D3: test cx, cx
7C92C7D6: jz Label_7C92C7E4
7C92C7D8: mov [edx], cx
7C92C7DB: inc edx
7C92C7DC: inc edx
7C92C7DD: inc esi
7C92C7DE: inc esi
...(続く)...

24 :デフォルトの名無しさん:2021/06/21(月) 09:35:10.89 ID:6C6uvD3w.net
...(続き)...
7C92C7DF: dec dword [ebp+0xc]
7C92C7E2: jnz Label_7C92C7D0
Label_7C92C7E4:
7C92C7E4: cmp dword [ebp+0xc], 0x0 # jump_from : 7C92C7D6
7C92C7E8: pop esi
7C92C7E9: jz Label_7C9138BF
Label_7C92C7EF:
7C92C7EF: and word [edx], 0x0 # jump_from : 7C9138C6
Label_7C92C7F3:
7C92C7F3: pop ebp # jump_from : 7C98E43C
7C92C7F4: ret 0xc
Label_7C98E437:
7C98E437: mov eax, 0x80070057 # jump_from : 7C92C7C3
7C98E43C: jmp Label_7C92C7F3
end proc

よろしくお願いいたします。

25 :デフォルトの名無しさん:2021/06/21(月) 11:07:32.85 ID:6C6uvD3w.net
>>23-24
入口は7C92C7B9から。出口は
7C92C7F3: pop ebp # jump_from : 7C98E43C
7C92C7F4: ret 0xc
である。0xc == 12だから関数Func7C92C7B9の引数はおそらく3個。
「7C92C7B9: mov edi, edi」は何もしない。
7C92C7BB: push ebp
7C92C7BC: mov ebp, esp
スタックフレームを確立。その直後、
ESP=EBP=[(old EBP), (復帰アドレス), Func7C92C7B9.#1, Func7C92C7B9.#2, Func7C92C7B9.#3]
となっている。
7C92C7BE: xor eax, eax
eaxをゼロクリア。
7C92C7C0: cmp [ebp+0xc], eax
7C92C7C3: jz Label_7C98E437
Func7C92C7B9.#2とeax(==0)を比較し、等しければLabel_7C98E437に飛ぶ。
すなわち if (Func7C92C7B9.#2 == 0) goto Label_7C98E437;
7C92C7C9: mov edx, [ebp+0x8]
Func7C92C7B9.#1をedxに代入する。
7C92C7CC: push esi
esiをスタックに保存する。
EBP=[(old EBP), (復帰アドレス), Func7C92C7B9.#1, Func7C92C7B9.#2, Func7C92C7B9.#3]
ESP=[(old ESI), (old EBP), (復帰アドレス), Func7C92C7B9.#1, Func7C92C7B9.#2, Func7C92C7B9.#3]
7C92C7CD: mov esi, [ebp+0x10]
Func7C92C7B9.#3をESIに代入する。
Label_7C92C7D0:
7C92C7D0: mov cx, [esi]
これはcx = *(WORD*)esi; と解釈される。
7C92C7D3: test cx, cx
7C92C7D6: jz Label_7C92C7E4
...(続く)...

26 :デフォルトの名無しさん:2021/06/21(月) 11:09:09.06 ID:6C6uvD3w.net
...(続き)...
cxがゼロならばLabel_7C92C7E4に飛ぶ。
すなわちif (*(WORD*)esi == 0) goto Label_7C92C7E4;
7C92C7D8: mov [edx], cx
これは*(WORD*)edx = *(WORD*)esi; と解釈される。
7C92C7DB: inc edx
7C92C7DC: inc edx
7C92C7DD: inc esi
7C92C7DE: inc esi
edxとesiをそれぞれ2だけ増やす。
7C92C7DF: dec dword [ebp+0xc]
ここで[ebp+0xc]は、Func7C92C7B9.#2であった。
Func7C92C7B9.#2を1だけ減らし、減してた結果がゼロならZeroFlagをTRUEにする。
7C92C7E2: jnz Label_7C92C7D0
ZeroFlagがFALSEならばLabel_7C92C7D0に飛ぶ。
Label_7C92C7E4:
7C92C7E4: cmp dword [ebp+0xc], 0x0 # jump_from : 7C92C7D6
Func7C92C7B9.#2とゼロを比較する。
7C92C7E8: pop esi
esiを元に戻す。
EBP=[(old EBP), (復帰アドレス), Func7C92C7B9.#1, Func7C92C7B9.#2, Func7C92C7B9.#3]
ESP=[(old EBP), (復帰アドレス), Func7C92C7B9.#1, Func7C92C7B9.#2, Func7C92C7B9.#3]
7C92C7E9: jz Label_7C9138BF
Func7C92C7B9.#2とゼロが等しければ、Label_7C9138BFに飛ぶ。
Label_7C92C7EF:
7C92C7EF: and word [edx], 0x0 # jump_from : 7C9138C6
*(WORD*)edxをゼロにする。
Label_7C92C7F3:
7C92C7F3: pop ebp # jump_from : 7C98E43C
7C92C7F4: ret 0xc
...(続く)...

27 :デフォルトの名無しさん:2021/06/21(月) 11:11:17.74 ID:6C6uvD3w.net
...(続き)...
関数Func7C92C7B9から戻る。戻り値はeaxまたはなし。
Label_7C98E437:
7C98E437: mov eax, 0x80070057 # jump_from : 7C92C7C3
7C98E43C: jmp Label_7C92C7F3
0x80070057はおそらくE_INVALIDARG。
eax にE_INVALIDARGを代入してLabel_7C92C7F3へ飛ぶ。
Label_7C9138BFについて:
7C9138BF: dec edx # jump_from : 7C92C7E9
7C9138C0: dec edx
7C9138C1: mov eax, 0x8007007a
7C9138C6: jmp Label_7C92C7EF
edxを2だけ減らし、eaxにE_NOT_SUFFICIENT_BUFFERを代入してLabel_7C92C7EFに飛ぶ。
...(続く)...

28 :デフォルトの名無しさん:2021/06/21(月) 11:13:11.16 ID:6C6uvD3w.net
...(続き)...
整理すると

HRESULT Func7C92C7B9(LPWSTR pszDest, DWORD cchDest, LPCWSTR pszSrc)
{
  LPWSTR dest = pszDest;
  LPCWSTR src = pszSrc;
  if (cchDest == 0) return E_INVALIDARG;
  do
  {
    if (*src == 0) break;
    *dest++ = *src++;
  } while (--cchDest != 0);
  if (cchDest == 0)
  {
    --dest;
    *dest = 0;
    return E_NOT_SUFFICIENT_BUFFER;
  }
  *dest = 0;
  return S_OK;
}

これで逆コンパイルは完了。
この関数はおそらく<strsafe.h>のStringCchCopyWだと思われる。  □

29 :デフォルトの名無しさん:2021/06/21(月) 11:44:38.13 ID:6C6uvD3w.net
【依頼の目的と内容説明】 shell32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
長いのでこちらに貼ります:
https://justpaste.it/6e2t2

Func7C92C7B9は前述のStringCchCopyW関数です。
Func7C92EC80の引数は不明ですが、戻り値がvoidでecxをチェックすることが分かっています。
shlwapi.dll!448は、VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)です。
shlwapi.dll!456は、BOOL WINAPI PathIsValidCharW(WCHAR c, DWORD class)です。
長いですが、解析お願いします。

30 :デフォルトの名無しさん:2021/06/21(月) 19:19:37.61 ID:6C6uvD3w.net
>>29
補足します。
[0x7c8d20f4]は、shlwapi.dll!PathGetDriveNumberWです。
[0x7c8d2070]は、shlwapi.dll!StrChrWです。

31 :デフォルトの名無しさん:2021/06/22(火) 23:46:23.94 ID:r0+t7d7W.net
>>29-30
すみません。ちょっと難しすぎてデコードできない。
今回は見送っておくよ。

32 :デフォルトの名無しさん:2021/06/23(水) 08:58:52.22 ID:VZC5/Bjf.net
【依頼の目的と内容説明】 shell32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
https://justpaste.it/9pwe4
解読お願いします。

33 :デフォルトの名無しさん:2021/06/23(水) 14:11:48.77 ID:VZC5/Bjf.net
>>32

https://wtools.io/paste-code/b58W

Func7C903F7Fは拡張子に関する探索を行う関数とみられる。
Func7C8FF2D3は絶対パスかチェックする関数とみられる。
Func7C9A5238は絶対パスを構築する関数とみられる。

34 :デフォルトの名無しさん:2021/06/24(木) 14:47:00.14 ID:70oiT5zZ.net
小学生が大人に九九暗唱してみせれば微笑ましいが
大人が大人に九九暗唱してみせるなら不気味で滑稽である

35 :デフォルトの名無しさん:2021/06/24(木) 16:39:48.53 ID:KFTtHP2O.net
複雑怪奇なアセンブリだけど、どうやって逆アセしてるんですか?

36 :デフォルトの名無しさん:2021/06/24(木) 16:41:35.70 ID:GPZ7ub3d.net
>>35
逆汗にはCodeReverse2というソフトを使用した。
ビルドさえ出来れば無料で使用できる。

katahiromz/CodeReverse2
https://github.com/katahiromz/CodeReverse2

37 :デフォルトの名無しさん:2021/06/24(木) 17:12:02.26 ID:KFTtHP2O.net
普通にgit cloneしたけど、ビルド出来ないよ

38 :デフォルトの名無しさん:2021/06/24(木) 17:15:49.84 ID:GPZ7ub3d.net
>>37

CodeReverse2は、udis86というサブモジュールを含んでいるので
単純なgit cloneだけでは取得できない。詳しくはこちらのページ:

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB

の「サブモジュールを含むプロジェクトのクローン」を参照されたい。

39 :デフォルトの名無しさん:2021/06/24(木) 17:20:01.56 ID:KFTtHP2O.net
わかった。git cloneに--recursiveを付ければダウンロードできるんだ。ありがとう

git clone --recursive https://github.com/katahiromz/CodeReverse2

40 :デフォルトの名無しさん:2021/06/24(木) 18:02:34.25 ID:KFTtHP2O.net
早くしないとx86 PC死んじゃうよ(何を)。

41 :デフォルトの名無しさん:2021/06/24(木) 19:04:47.18 ID:VS1e3y9e.net
katayamaさんは秀才

42 :デフォルトの名無しさん:2021/06/24(木) 19:30:04.89 ID:GPZ7ub3d.net
世の中には様々な逆コンパがあるが、コンピュータの歴史上、一般のPC上で
無料で正確なコードを出力するものは存在しない。ある程度性能のある逆コンパは、
車一台買えるような値段になる。

しかも、従来の逆コンパは、本当の逆変換になっていない未熟なものである
(つまり、逆コンパしたコードはほとんどコンパイルできない)。

情報技術者のほとんどが人間の考えを機械の言葉にすることを考えてきたが、
逆に機械語をプログラミングの言葉に直そうと考えて究極の答えにたどり着いた人は
ほとんど居ない。

私は、人間にもコンピュータにも分かる、トレース(追跡)可能な逆コンパ用の言葉が
必要だと考えている。

まず、一般的にアセンブリは次のように「```asm」と「```」という二つの行で囲って表すこととする。

```asm
push eax
pop ebx
```

これはGitHubなどで使われているMarkDownと同じ記述方法であるので
受け入れ可能であろう。「`」はバッククォートという記号であり、日本語109キー
ボードではShift+@で入力できる。

43 :デフォルトの名無しさん:2021/06/24(木) 19:32:52.43 ID:m+XEGxhu.net
バッククォートくらい知っとるわアホが

44 :デフォルトの名無しさん:2021/06/24(木) 19:38:00.14 ID:GPZ7ub3d.net
アセンブリは左側に仮想アドレスを書いてもよい。

```asm
7CAB1C58: mov ebp, esp
7CAB1C5A: mov ecx, [ebp+0x8]
```

この場合「mov ebp, esp」は仮想アドレス0x7CAB1C58にあり、
「mov ecx, [ebp+0x8]」は仮想アドレス0x7CAB1C5Aにある。
「:」はコロンという記号である。

また、ジャンプ先のラベルを表す一行をアセンブリに記載してもよい。
例えば、次の「Label_7CAB1C55:」はラベル行を表す。

```asm
Label_7CAB1C55:
7CAB1C55: mov edi, edi
7CAB1C57: push ebp
```

45 :デフォルトの名無しさん:2021/06/24(木) 20:46:18.12 ID:GPZ7ub3d.net
私が考えているのは、2つのプログラムに対する演算や関係を記述するメタ言語である。
次のような記号を考えよう。

```x
PX
```
[===]
```y
PY
```
上記は「言語Xのプログラム「PX」は言語Yのプログラム「PY」と同値である」と読む。
[===]は、プログラムの同値関係を表す記号である。

```x
PX
```
[==]
```y
PY
```
上記は「言語Xのプログラム「PX」は言語Yのプログラム「PY」と(ほとんど)同じ意味である」と読む。

```x
PX
```
[=>]
```y
PY
```
上記は「言語Xのプログラム「PX」から言語Yのプログラム「PY」が導出される」と読む。
[=>]は、プログラムの導出を表す記号である。

46 :デフォルトの名無しさん:2021/06/24(木) 21:03:40.76 ID:GPZ7ub3d.net
実際にコードが記述されているプログラムを実引数として変換を行う方法を考えよう。

MarkDown形式の三連バッククォートで囲って実際に記載されているコードを「実コード」と呼び、
実コードに対する代名詞を「仮コード」と呼ぶことにする。

実コードを抽象化すると仮コードの名前になる。
例えば、>>45
```x
PX
```
をPX0という代名詞で表し、
```y
PY
```
をPY0という代名詞で表すとき、「PX0[===]PY0」、「PX0[==]PY0」、「PX0[=>]PY0」などと記述できる。

47 :デフォルトの名無しさん:2021/06/24(木) 21:15:17.55 ID:GPZ7ub3d.net
Pを変数とするメタ関数Fを「[F][(]P[)]」と表すことにする。
また、Fを仮コードpに施したものを「[F][(]p[)]」と表すことにする。
MarkDownの三連バッククォート記法に従うなら、「[F][(]p[)]」の仮コード「p」を
実コードに置き換えてもいい。
メタ関数の引数が2つや3つの場合も「[F][(]a[,]b[,]c[)]」などと記述する。

メタ関数名やメタ記号を角かっこ [ ] で囲っているのは、実際のプログラムで
使用している記号との混同を避けるためである。

48 :デフォルトの名無しさん:2021/06/24(木) 22:06:26.29 ID:KFTtHP2O.net
だとすれば、形式言語で書くと
```asm
push eax
pop ebx
```
[==]
```asm
mov ebx, eax
```
とか、
```asm
xor eax, eax
```
[==]
```asm
mov eax, 0
```
とか書けますね(だからどうした

49 :デフォルトの名無しさん:2021/06/24(木) 22:14:16.13 ID:KFTtHP2O.net
形式言語はバッククォート表記のせいで無駄に行数を喰いますね。

「push eax; pop ebx」[==]「mov ebx, eax」
これじゃいけないんすか?

50 :デフォルトの名無しさん:2021/06/24(木) 22:36:01.24 ID:GPZ7ub3d.net
>>49
ちゃんと言語名を明記すべき。行区切りは全角の「/」にしよう。

asm「push eax/pop ebx」[==] asm「mov ebx, eax」

これならバッククォート表記と整合性が図れる。
でも全角文字は英語圏では使いづらいので日本語圏に限定するしかない。

51 :デフォルトの名無しさん:2021/06/24(木) 22:51:38.01 ID:GPZ7ub3d.net
要するに、アセンブリとC/C++言語の中間言語「cr2言語(仮)」を考えているんだろ。

アセンブリは広大な言語空間だから、素人の人間が手作業でちまちまやっていたら
何カ月経っても制覇できない。

インターネットで公開データが気軽にダウンロードできる時代だから、
データ指向でCPUの全命令を一気に網羅することを考えないといけない。
生データがなければウェブからスクレイピングするとか。。。

x86/x64 CPU の仕様は
「Intel 64 and IA-32 Architectures Software Developer’s Manual」に
全部書かれていて、PDFファイルとしてダウンロードできる(一次情報)。

52 :デフォルトの名無しさん:2021/06/24(木) 23:03:34.25 ID:GPZ7ub3d.net
ほらよ:
https://github.com/netwide-assembler/nasm/blob/master/x86/insns.dat

全部で6256行あるぜ。これを手作業で変換処理を書くつもりか???

正気かよ

53 :デフォルトの名無しさん:2021/06/24(木) 23:16:42.66 ID:KFTtHP2O.net
>>52
ありがとう
早速解読してみるね。なんか英語で書かれてて難しそう。。。

54 :デフォルトの名無しさん:2021/06/25(金) 00:46:15.53 ID:xLwe8284.net
解読していくと。。。
使い方を知りたいならinsns.plを読みなさいと。
拡張子.plはPerlだよな。
うわ、こんな所でPerlが出てくるのか。

55 :デフォルトの名無しさん:2021/06/25(金) 01:46:22.63 ID:xLwe8284.net
https://www.felixcloutier.com/x86/cmpxchg8b:cmpxchg16b

こんなサイトをスクレイピングすれば〜?

56 :デフォルトの名無しさん:2021/06/25(金) 12:06:59.81 ID:W5hhXd/9.net
【依頼の目的と内容説明】 user32.dll/imm32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
proc user32.dll!CliImmSetHotKey@16 Label_773C7479
Label_773C7479:
mov edi, edi
push ebp
mov ebp, esp
push esi
push edi
mov edi, [ebp+0x10]
xor eax, eax
test edi, edi
setz al
test eax, eax
jz Label_773C74A6
push eax
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func773C7273@20
mov esi, eax
test esi, esi
jnz Label_773C74D4
jmp Label_773C74E5
Label_773C74A6:
push 0x2 # jump_from : 773C748C
push dword [ebp+0x14]
(...続く...)

57 :デフォルトの名無しさん:2021/06/25(金) 12:07:44.35 ID:W5hhXd/9.net
...(続き)...
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func77384A58@20
mov esi, eax
test esi, esi
jz Label_773C74E5
push 0x0
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func773C7273@20
mov esi, eax
test esi, esi
jnz Label_773C74E5
Label_773C74D4:
push 0x1 # jump_from : 773C74A2
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func77384A44@20
Label_773C74E5:
pop edi # jump_from : 773C74A4 773C74BB 773C74D2
mov eax, esi
pop esi
pop ebp
ret 0x10
end proc
よろしくお願いします。

58 :デフォルトの名無しさん:2021/06/25(金) 13:00:01.37 ID:W5hhXd/9.net
>>56-57
asm「mov edi, edi」
[=>] txt「何もしない。」

asm「push ebp/mov ebp, esp」
[=>] txt「スタックフレームを確立する。
EBP=ESP=[(old bpb), (ret. addr.), CliImmSetHotKey.#1, CliImmSetHotKey.#2, CliImmSetHotKey.#3, CliImmSetHotKey.#4].」

asm「push esi/push edi」
[=>] txt「esiをプッシュする。ediをプッシュする。
ESP=[(old edi), (old esi), (old bpb), (ret. addr.), CliImmSetHotKey.#1, CliImmSetHotKey.#2, ...].」

asm「mov edi, [ebp+0x10]/xor eax, eax/test edi, edi/setz al/test eax, eax/jz Label_773C74A6」
[=>]
```txt
edi = CliImmSetHotKey.#3;
eax = 0;
ZeroFlag = (edi == 0);
al = (ZeroFlag == TRUE);
if (eax == 0) goto Label_773C74A6;
```
...(続く)...

59 :デフォルトの名無しさん:2021/06/25(金) 13:01:12.12 ID:W5hhXd/9.net
...(続き)...
```asm
push eax
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func773C7273@20
```
[=>]
```txt
assert(eax == 1);
eax = Func773C7273(CliImmSetHotKey.#1, CliImmSetHotKey.#2, edi, CliImmSetHotKey.#4, eax);
```
asm「mov esi, eax/test esi, esi/jnz Label_773C74D4/jmp Label_773C74E5」
[=>] txt「esi = eax;/ZeroFlag = (esi == 0);/if (!ZeroFlag) goto Label_773C74D4;/goto Label_773C74E5;」

```asm
Label_773C74A6:
push 0x2 # jump_from : 773C748C
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func77384A58@20
```
[=>]
```txt
Label_773C74A6:
eax = Func77384A58(CliImmSetHotKey.#1, CliImmSetHotKey.#2, edi, CliImmSetHotKey.#4, 0x2);
```
...(続く)...

60 :デフォルトの名無しさん:2021/06/25(金) 13:02:50.65 ID:W5hhXd/9.net
...(続き)...
asm「mov esi, eax/test esi, esi/jz Label_773C74E5」
[=>] txt「esi = eax;/ZeroFlag = (esi == 0);/if (ZeroFlag) goto Label_773C74E5;」
```asm
push 0x0
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func773C7273@20
```
[=>] txt「eax = Func773C7273(CliImmSetHotKey.#1, CliImmSetHotKey.#2, edi, CliImmSetHotKey.#4, 0);」

asm「mov esi, eax/test esi, esi/jnz Label_773C74E5」
[=>] txt「esi = eax;/if (esi != 0) goto Label_773C74E5;」

```asm
Label_773C74D4:
push 0x1 # jump_from : 773C74A2
push dword [ebp+0x14]
push edi
push dword [ebp+0xc]
push dword [ebp+0x8]
call Func77384A44@20
```
[=>]
```txt
Label_773C74D4:
eax = Func77384A44(CliImmSetHotKey.#1, CliImmSetHotKey.#2, edi, CliImmSetHotKey.#4, 1);
```
...(続く)...

61 :デフォルトの名無しさん:2021/06/25(金) 13:03:52.02 ID:W5hhXd/9.net
...(続き)...
```asm
Label_773C74E5:
pop edi # jump_from : 773C74A4 773C74BB 773C74D2
mov eax, esi
pop esi
pop ebp
ret 0x10
```
[=>]
```txt
Label_773C74E5:
eax = esi;
スタックフレームを破棄する。
return eax;
```

以上を簡略化し、ImmSetHotKeyのプロトタイプが
BOOL WINAPI ImmSetHotKey(DWORD dwHotKeyID, UINT uModifiers, UINT uVKey, HKL hKL);
であることを鑑みると

...(続く)...

62 :デフォルトの名無しさん:2021/06/25(金) 13:04:32.70 ID:W5hhXd/9.net
...(続き)...

```c
BOOL CliImmSetHotKey(DWORD dwHotKeyID, UINT uModifiers, UINT uVKey, HKL hKL)
{
__BOOL ret;
__if (uVKey != 0)
__{
____ret = Func773C7273(dwHotKeyID, uModifiers, uVKey, hKL, 1);
____if (ret != 0)
______Func77384A44(dwHotKeyID, uModifiers, uVKey, hKL, 1);
____return ret;
__}
__ret = Func77384A58(dwHotKeyID, uModifiers, uVKey, hKL, 2);
__if (ret == 0)
____return ret;
__ret = Func773C7273(dwHotKeyID, uModifiers, uVKey, hKL, 0);
__if (ret != 0)
____return ret;
__Func77384A44(dwHotKeyID, uModifiers, uVKey, hKL, 1);
__return ret;
}
```
となって逆コンパイルが完了する。 □

63 :デフォルトの名無しさん:2021/06/25(金) 13:36:57.11 ID:W5hhXd/9.net
【依頼の目的と内容説明】 user32.dll/imm32.dllの解析
【プロセッサの種類】 x86 【OSの種類】 Win Server 2003 【言語】 C/C++
【報酬金額と送金方法】 報酬なし
【アセンブリまたは機械語】
proc Func77384A44@20 Label_77384A44
Label_77384A44:
mov eax, 0x1201
mov edx, 0x7ffe0300
call dword [edx]
ret 0x14
end proc

解読お願いします。

[0x7ffe0300]は、ntdll!KiFastSystemCallであることが分かっています。

64 :デフォルトの名無しさん:2021/06/25(金) 23:03:34.71 ID:W5hhXd/9.net
>>63
NtUserSetImeHotKey関数をシステムコール経由で呼んでいるらしい。
https://reactos.org/wiki/Techwiki:Win32k/syscalls

これ以上のことは分からない。

65 :デフォルトの名無しさん:2021/06/26(土) 23:13:53.65 ID:RPMP544+.net
こっちでまとめてます。秘密基地です。
https://github.com/katahiromz/secret_base

66 :デフォルトの名無しさん:2021/06/29(火) 20:06:52.90 ID:+6dhbc6a.net
```asm
neg eax
sbb eax, eax
```
[=>]
```txt
CarryFlag = (eax != 0);
eax = -(LONG)eax;
eax -= eax + CarryFlag;
```
Devide the cases about CarryFlag and we get:
```c-like
if (eax != 0)
eax = 0xFFFFFFFF;
else
eax = 0;
```
これがneg-sbbのトリック。

67 :デフォルトの名無しさん:2021/07/13(火) 10:27:53.03 ID:M2x6Ny3W.net
riscはオナニーしながらでも読めるにゃ

68 :デフォルトの名無しさん:2021/07/13(火) 11:39:35.80 ID:EvOOyjG8.net
はやっ

69 :デフォルトの名無しさん:2021/07/14(水) 01:35:31.92 ID:lv8+vNga.net
>>66
```asm
neg eax
sbb eax, eax
```

これにさらに「inc eax」が付くとこうなる:


```asm
neg eax
sbb eax, eax
inc eax
```
[=>]
```c
if (eax != 0) eax = 0;
else eax = 1;
```

つまり、eaxの論理否定となる。

70 :デフォルトの名無しさん:2021/08/03(火) 21:07:31.90 ID:Q9+5cbUY.net
```txt
Label_YYYY:
...
if (exp) goto Label_YYYY;
```
のような場合は
```txt
do
...
if (exp) goto Label_YYYY;
```



```txt
if (exp) goto Label_XXXX;
...
Label_XXXX:
...
```
のような並びがあるときは、
```txt
if (!(exp)) {
...
}
...
```
に書き換えることができる。

71 :デフォルトの名無しさん:2021/08/03(火) 21:09:13.31 ID:Q9+5cbUY.net
>>70は書き損じだから無視して。


```txt
Label_YYYY:
...
if (exp) goto Label_YYYY;
```
は、
```txt
do
...
} while (exp);
```
に置き換えることができる。


```txt
if (exp) goto Label_XXXX;
...
Label_XXXX:
...
```
は、
```txt
if (!(exp)) {
...
}
...
```
に書き換えることができる。

72 :デフォルトの名無しさん:2021/08/03(火) 21:16:45.35 ID:Q9+5cbUY.net
ジャンプ命令は基本的にgoto文に置き換えることができる。

ジャンプ命令の符号あり符号なしの区別は

http://www.unixwiz.net/techtips/x86-jumps.html

にまとまっている。例えば、JA命令はJump if aboveだからunsignedであり、JL命令はJump if lessだからsignedである。

```asm
cmp X, Y
ja Label_ZZZZ
```
の場合は、
```txt
if ((unsigned)X > (unsigned)Y) goto Label_ZZZZ;
```
と書き換えることができる。

「test X, Y」はXとYのビット論理積の結果によってフラグを更新する。

例えば
```asm
test eax, eax
jz Label_XXXX
```

```txt
if (eax == 0) goto Label_XXXX;
```
に置き換え可能。

73 :デフォルトの名無しさん:2021/08/04(水) 15:25:34.02 ID:YCRiyQzz.net
if (exp)

74 :デフォルトの名無しさん:2021/08/04(水) 15:26:28.93 ID:YCRiyQzz.net
```txt
if (exp)
{
...
goto Label_XXXX;
}
...
Label_XXXX:
```
は、
if (exp)
{
...
}
else
...
Label_XXXX:
```

75 :デフォルトの名無しさん:2021/08/04(水) 15:27:12.21 ID:YCRiyQzz.net
```txt
if (exp) {
...
goto Label_XXXX;
}
...
Label_XXXX:
```
は、
if (exp) {
...
} else {
...
}
Label_XXXX:
```
に置き換え可能。

76 :デフォルトの名無しさん:2021/08/13(金) 14:20:39.59 ID:xGO78+x4.net
ImmAssociateContext
ImmAssociateContextEx
ImmConfigureIMEA/W
ImmEscapeA/W
Imm32GetClientImcCache
ImmGetCompositionStringA/W
ImmGetContext
ImmInstallIMEW
ImmIsUIMessageA/W
ImmRequestMessageA/W
ImmSetCompositionStringA/W
ImmGetImeMenuItemsA/W
ImmLockIMC
ImmGenerateMessage
ImmTranslateMessage
ImmProcessKey
ImmSetActiveContext

宿題がまだこ〜んなにあるぜ。本当に全部できるのかよ。

77 :デフォルトの名無しさん:2021/09/24(金) 02:14:10.10 ID:i//SzVJC.net
まあ、これを見て実際の逆工学をやってみるもよし

https://github.com/katahiromz/DecodersTatami/blob/main/target/analysis/Func00401550.txt

セキュリティエンジニアの道ははるかに遠い

78 :デフォルトの名無しさん:2021/09/25(土) 20:48:50.24 ID:H+l7h9ZE.net
とりあえず、x86 CPUについて復習しようね。

eax, ebx, ecx, edx。
この4つは汎用レジスタで、それぞれ32ビット整数。

esp, ebp。
この二つは特にスタックに使われるレジスタ。

eaxの中には16ビット整数のaxがある。axはeaxの下位16ビット整数。
ebxの中には16ビット整数のbxがある。bxはebxの下位16ビット整数。
ecxの中には16ビット整数のcxがある。cxはecxの下位16ビット整数。
edxの中には16ビット整数のdxがある。dxはedxの下位16ビット整数。

79 :デフォルトの名無しさん:2021/09/25(土) 20:52:28.04 ID:H+l7h9ZE.net
axはalとahの2つに分かれている。alはaxの下位8ビットで、ahはaxの上位8ビット。
bxはblとbhの2つに分かれている。blはbxの下位8ビットで、bhはbxの上位8ビット。
cxはclとchの2つに分かれている。clはcxの下位8ビットで、chはcxの上位8ビット。
dxはdlとdhの2つに分かれている。dlはdxの下位8ビットで、dhはdxの上位8ビット。

esi, edi。
この2つのレジスタは、メモリーの転送によく使われる。
esiのなかには16ビット整数のsiがある。siはesiの下位16ビット整数。
ediのなかには16ビット整数のdiがある。diはediの下位16ビット整数。
esiのsはsourceで、ediのdはdestinationだ。

80 :デフォルトの名無しさん:2021/09/25(土) 21:08:38.10 ID:+1RCibwo.net
eaxの中にaxレジスタがあり、axレジスタの中にal, ahレジスタがあるという見方もできる。このような構造になっているのは16ビットとの互換性のためである。

64ビットCPUのx64、別名amd64ではrax, rbx, rcx, rdxというように、頭にrが付いた64ビットレジスタが増設された。逆工学の主な戦場はまだ32ビットにあるが、今後64ビットを対応しないといけない。

81 :デフォルトの名無しさん:2021/09/28(火) 20:27:04.96 ID:m9n91EHz.net
【問題】
```asm
push 0x30
mov edi, eax
pop ecx
```

【解読】
まず、
`push 0x30`と`mov edi, eax`は独立しているので交換可能。

```asm
mov edi, eax
push 0x30
pop ecx
```

さらに`push 0x30`と`pop ecx`が並んでいるので、これは`ecx = 0x30;`と解釈できる。

よって

```asm
push 0x30
mov edi, eax
pop ecx
```
[=>]

82 :デフォルトの名無しさん:2021/09/28(火) 20:29:43.46 ID:m9n91EHz.net
```txt
edi = eax;
ecx = 0x30;
```
である。□

```asm
push (即値)
pop (レジスタX)
```
[=>]
```txt
(レジスタX) = (即値);
```
はpush-popトリックだから覚えておいてね。

83 :デフォルトの名無しさん:2022/01/17(月) 19:44:42.22 ID:32ay/bkz.net
今回は、Win32 FileID APIs 1.1の解読をします。
duck.com で「FileID APIs 1.1」を検索し、FileID APIs 1.1をこっそりダウンロード。
最適化なしで、次のソースをビルドします。

#define _WIN32_WINNT 0x400
#include <windows.h>
#include "fileextd.h"
int main(void)
{
SetFileInformationByHandle((HANDLE)0xDEADFACE, FileBasicInfo, NULL, 0);
GetFileInformationByHandleEx((HANDLE)0xDEADFACE, FileBasicInfo, NULL, 0);
OpenFileById((HANDLE)0xDEADFACE, NULL, 0, 0, NULL, 0);
return 0;
}

これをDecodersTatamiに掛けてdeadfaceをgrep検索します。

84 :デフォルトの名無しさん:2022/01/17(月) 19:45:19.85 ID:32ay/bkz.net
これをDecodersTatamiに掛けてdeadfaceをgrep検索します。
main関数が見つかります。呼び出しツリーは以下のようになります。

main
...→ Func00401341 // SetFileInformationByHandle
......→ Func0040105F
......→ Func004010B9
...→ Func0040122D // GetFileInformationByHandleEx
......→ Func00401032
......→ Func004010B9
...→ Func004010D7 // OpenFileById
......→ Func004010B9

というわけで、最初にFunc004010B9を解読します。

85 :デフォルトの名無しさん:2022/01/17(月) 19:46:57.43 ID:32ay/bkz.net
【依頼の目的と内容説明】Win32 FileID APIs 1.1
【プロセッサの種類】x86
【OSの種類】Windows
【言語】C/C++
【報酬金額と送金方法】報酬なし
【アセンブリまたは機械語】

```asm
proc Func004010B9@4 Label_004010B9
attrs [[stdcall]]
# call_from : 004010D7 0040122D 00401341
# call_to : 0040108C
Label_004010B9:
004010B9: 8B FF : mov edi, edi
004010BB: 55 : push ebp
004010BC: 8B EC : mov ebp, esp
004010BE: 56 : push esi
004010BF: FF 75 08 : push dword [ebp+0x8]
004010C2: E8 C5 FF FF FF : call Func0040108C@4
004010C7: 8B F0 : mov esi, eax
004010C9: 56 : push esi
004010CA: FF 15 08 80 40 00 : call kernel32.dll!SetLastError
004010D0: 8B C6 : mov eax, esi
004010D2: 5E : pop esi
004010D3: 5D : pop ebp
004010D4: C2 04 00 : ret 0x4
end proc
```

86 :デフォルトの名無しさん:2022/01/17(月) 19:50:05.81 ID:32ay/bkz.net
これは非常に簡単だ。

```txt
UNKNOWN Func004010B9(UNKNOWN ARGV[1])
{
Push esi;
esi = eax = Func0040108C(ARGV[1]);
SetLastError(esi);
eax = esi;
Pop esi;
return eax;
}
```

単純化して
```txt
DWORD Func004010B9(UNKNOWN ARGV[1])
{
DWORD dwError = Func0040108C(ARGV[1]);
SetLastError(dwError);
return dwError;
}
```

87 :デフォルトの名無しさん:2022/01/17(月) 19:53:15.58 ID:32ay/bkz.net
おそらくFunc0040108Cはエラーコードを返す。
また、typeof(Func004010B9.ARGV[1]) == typeof(Func0040108C.ARGV[1])であることがわかる。

ではFunc0040108Cを見てみよう。

```asm
proc Func0040108C Label_0040108C
attrs [[noreturn]]
# call_from : 004010B9
# jump_to : 004010B6
Label_0040108C:
0040108C: 8B FF : mov edi, edi
0040108E: 55 : push ebp
0040108F: 8B EC : mov ebp, esp
00401091: A1 B0 DD 40 00 : mov eax, [0x40ddb0]
00401096: 85 C0 : test eax, eax
00401098: 75 1C : jnz Label_004010B6
0040109A: 68 58 81 40 00 : push 0x408158
0040109F: FF 15 04 80 40 00 : call kernel32.dll!GetModuleHandleA
004010A5: 68 AC 81 40 00 : push 0x4081ac
004010AA: 50 : push eax
004010AB: FF 15 00 80 40 00 : call kernel32.dll!GetProcAddress
004010B1: A3 B0 DD 40 00 : mov [0x40ddb0], eax
Label_004010B6:
004010B6: 5D : pop ebp # jump_from : 00401098
004010B7: FF E0 : jmp eax
end proc
```asm

88 :デフォルトの名無しさん:2022/01/17(月) 20:00:34.53 ID:32ay/bkz.net
解読する。

```asm
DWORD Func0040108C(UNKNOWN ARGV[1])
{
eax = [0x40ddb0];
if (eax) goto Label_004010B6;
eax = GetModuleHandleA(0x408158);
[0x40ddb0] = eax = GetProcAddress(eax, 0x4081ac);
Label_004010B6:
return eax;
}
```

[0x40ddb0]はおそらく関数ポインタのキャッシュだ。
0x408158と0x4081acはANSI文字列である。

decode.pyのCR2_OPTIONSに--read ...を追加して再デコード:

```python
CR2_OPTIONS = ['--addr', '--hex', '--read', '0x408158', '32', '--read', '0x4081ac', '32']
```

89 :デフォルトの名無しさん:2022/01/17(月) 20:05:56.89 ID:32ay/bkz.net
次の結果が得られる。

```txt
## Read Memory ##
+ADDRESS +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
00408158 4E 54 44 4C 4C 2E 44 4C 4C 00 00 00 4E 74 51 75 NTDLL.DLL NtQu
00408168 65 72 79 49 6E 66 6F 72 6D 61 74 69 6F 6E 46 69 eryInformationFi
32 (0x20) bytes read.

## Read Memory ##
+ADDRESS +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
004081AC 52 74 6C 4E 74 53 74 61 74 75 73 54 6F 44 6F 73 RtlNtStatusToDos
004081BC 45 72 72 6F 72 00 00 00 00 00 00 00 05 00 00 C0 Error . .
32 (0x20) bytes read.
```

0x408158は「NTDLL.DLL」であり、0x4081acは「RtlNtStatusToDosError」である。
RtlNtStatusToDosErrorのプロトタイプは、検索して調べると
ULONG RtlNtStatusToDosError(NTSTATUS Status);
である。

90 :デフォルトの名無しさん:2022/01/17(月) 20:06:48.16 ID:32ay/bkz.net
よって整理すると

```txt
typedef ULONG (APIENTRY* FN_RtlNtStatusToDosError)(NTSTATUS);
FN_RtlNtStatusToDosError g_pRtlNtStatusToDosError = NULL;

DWORD Func0040108C(NTSTATUS Status)
{
if (!g_pRtlNtStatusToDosError)
g_pRtlNtStatusToDosError = (FN_RtlNtStatusToDosError)
GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "RtlNtStatusToDosError");
return g_pRtlNtStatusToDosError(Status);
}
```



続きはまた明日。

91 :デフォルトの名無しさん:2022/01/18(火) 10:34:45.36 ID:kpMFjbVI.net
typeof(Func004010B9.ARGV[1]) == NTSTATUSであることがわかった。最初、
004010B7: FF E0 : jmp eax
のところがよくわからなかったが、スタックフレームなしに関数ポインタに直接飛んでいることがわかった。
これをnoreturn-jmpトリックと呼ぶことにする。

次はFunc0040105F:

```asm
proc Func0040105F Label_0040105F
attrs [[noreturn]]
# call_from : 00401341
# jump_to : 00401089
Label_0040105F:
0040105F: 8B FF : mov edi, edi
00401061: 55 : push ebp
00401062: 8B EC : mov ebp, esp
00401064: A1 A8 DD 40 00 : mov eax, [0x40dda8]
00401069: 85 C0 : test eax, eax
0040106B: 75 1C : jnz Label_00401089
0040106D: 68 58 81 40 00 : push 0x408158
00401072: FF 15 04 80 40 00 : call kernel32.dll!GetModuleHandleA
00401078: 68 7C 81 40 00 : push 0x40817c
0040107D: 50 : push eax
0040107E: FF 15 00 80 40 00 : call kernel32.dll!GetProcAddress
00401084: A3 A8 DD 40 00 : mov [0x40dda8], eax
Label_00401089:
00401089: 5D : pop ebp # jump_from : 0040106B
0040108A: FF E0 : jmp eax
end proc
```

92 :デフォルトの名無しさん:2022/01/18(火) 10:36:01.65 ID:kpMFjbVI.net
これもnoreturn-jmpトリックのようだ。とりあえず、decode.pyのCR2_OPTIONSに--read ...を追加して再デコード:

```python
CR2_OPTIONS = ['--addr', '--hex', '--read', '0x408158', '32', '--read', '0x4081ac', '32', '--read', '0x408158', '32', '--read', '0x40817c', '32']
```

## Read Memory ##
+ADDRESS +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
00408158 4E 54 44 4C 4C 2E 44 4C 4C 00 00 00 4E 74 51 75 NTDLL.DLL NtQu
00408168 65 72 79 49 6E 66 6F 72 6D 61 74 69 6F 6E 46 69 eryInformationFi
32 (0x20) bytes read.

## Read Memory ##
+ADDRESS +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
0040817C 4E 74 53 65 74 49 6E 66 6F 72 6D 61 74 69 6F 6E NtSetInformation
0040818C 46 69 6C 65 00 00 00 00 4E 74 51 75 65 72 79 44 File NtQueryD
32 (0x20) bytes read.

「NTDLL.DLL」と「NtSetInformationFile」が得られた。NtSetInformationFileのプロトタイプは

93 :デフォルトの名無しさん:2022/01/18(火) 10:36:31.35 ID:kpMFjbVI.net
NTSTATUS NtSetInformationFile(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);

であるから、

typdef NTSTATUS (APIENTRY *FN_NtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
FN_NtSetInformationFile g_pNtSetInformationFile = NULL;

NTSTATUS APIENTRY Func0040105F(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass)
{
if (!g_pNtSetInformationFile)
g_pNtSetInformationFile = GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtSetInformationFile");
return (*g_pNtSetInformationFile)(FileHandle, IoStatusBlock, FileInformation, Length, FileInformationClass);
}



94 :デフォルトの名無しさん:2022/01/18(火) 10:45:00.41 ID:kpMFjbVI.net
次はFunc00401032。

```asm
proc Func00401032 Label_00401032
attrs [[noreturn]]
# call_from : 0040122D
# jump_to : 0040105C
Label_00401032:
00401032: 8B FF : mov edi, edi
00401034: 55 : push ebp
00401035: 8B EC : mov ebp, esp
00401037: A1 A4 DD 40 00 : mov eax, [0x40dda4]
0040103C: 85 C0 : test eax, eax
0040103E: 75 1C : jnz Label_0040105C
00401040: 68 58 81 40 00 : push 0x408158
00401045: FF 15 04 80 40 00 : call kernel32.dll!GetModuleHandleA
0040104B: 68 64 81 40 00 : push 0x408164
00401050: 50 : push eax
00401051: FF 15 00 80 40 00 : call kernel32.dll!GetProcAddress
00401057: A3 A4 DD 40 00 : mov [0x40dda4], eax
Label_0040105C:
0040105C: 5D : pop ebp # jump_from : 0040103E
0040105D: FF E0 : jmp eax
end proc
```

これもnoreturn-jmpトリック。

95 :デフォルトの名無しさん:2022/01/18(火) 10:45:21.84 ID:kpMFjbVI.net
decode.pyのCR2_OPTIONSに--read ...を追加して再デコード:

```python
CR2_OPTIONS = ['--addr', '--hex', '--read', '0x408158', '32', '--read', '0x4081ac', '32', '--read', '0x408158', '32', '--read', '0x40817c', '32', '--read', '0x408164', '32']
```

## Read Memory ##
+ADDRESS +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF
00408164 4E 74 51 75 65 72 79 49 6E 66 6F 72 6D 61 74 69 NtQueryInformati
00408174 6F 6E 46 69 6C 65 00 00 4E 74 53 65 74 49 6E 66 onFile NtSetInf
32 (0x20) bytes read.

NtQueryInformationFileのプロトタイプは

NTSTATUS NtQueryInformationFile(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);

であるから、

96 :デフォルトの名無しさん:2022/01/18(火) 10:45:51.37 ID:kpMFjbVI.net
typdef NTSTATUS (APIENTRY *FN_NtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
FN_NtQueryInformationFile g_pNtQueryInformationFile = NULL;

NTSTATUS Func00401032(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass)
{
if (!g_pNtQueryInformationFile)
g_pNtQueryInformationFile = (FN_NtQueryInformationFile)GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQueryInformationFile");
retuern (*g_pNtQueryInformationFile)(FileHandle, IoStatusBlock, FileInformation, Length, FileInformationClass);
}



続きは明日やろう。

97 :デフォルトの名無しさん:2022/11/28(月) 18:36:01.95 ID:QIQXhRT5.net
明日は来ない

総レス数 97
58 KB
掲示板に戻る 全部 前100 次100 最新50
read.cgi ver.24052200