X



アセンブリや機械語を解析して楽しむスレ
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
垢版 |
2021/06/19(土) 17:16:50.94ID:KpP01EPy
5ちゃんねるの総力を挙げて、人力でアセンブリや機械語を逆コンパイルするスレッドです。コード解析の達人やヒマ人の皆様、ご協力下さい。

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

依頼は一度に1関数までとします。あまりにも長いコードは人力では逆コンパイルできません。常識の範囲でご利用ください。
0047デフォルトの名無しさん
垢版 |
2021/06/24(木) 21:15:17.55ID:GPZ7ub3d
Pを変数とするメタ関数Fを「[F][(]P[)]」と表すことにする。
また、Fを仮コードpに施したものを「[F][(]p[)]」と表すことにする。
MarkDownの三連バッククォート記法に従うなら、「[F][(]p[)]」の仮コード「p」を
実コードに置き換えてもいい。
メタ関数の引数が2つや3つの場合も「[F][(]a[,]b[,]c[)]」などと記述する。

メタ関数名やメタ記号を角かっこ [ ] で囲っているのは、実際のプログラムで
使用している記号との混同を避けるためである。
0048デフォルトの名無しさん
垢版 |
2021/06/24(木) 22:06:26.29ID:KFTtHP2O
だとすれば、形式言語で書くと
```asm
push eax
pop ebx
```
[==]
```asm
mov ebx, eax
```
とか、
```asm
xor eax, eax
```
[==]
```asm
mov eax, 0
```
とか書けますね(だからどうした
0049デフォルトの名無しさん
垢版 |
2021/06/24(木) 22:14:16.13ID:KFTtHP2O
形式言語はバッククォート表記のせいで無駄に行数を喰いますね。

「push eax; pop ebx」[==]「mov ebx, eax」
これじゃいけないんすか?
0050デフォルトの名無しさん
垢版 |
2021/06/24(木) 22:36:01.24ID:GPZ7ub3d
>>49
ちゃんと言語名を明記すべき。行区切りは全角の「/」にしよう。

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

これならバッククォート表記と整合性が図れる。
でも全角文字は英語圏では使いづらいので日本語圏に限定するしかない。
0051デフォルトの名無しさん
垢版 |
2021/06/24(木) 22:51:38.01ID:GPZ7ub3d
要するに、アセンブリとC/C++言語の中間言語「cr2言語(仮)」を考えているんだろ。

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

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

x86/x64 CPU の仕様は
「Intel 64 and IA-32 Architectures Software Developer’s Manual」に
全部書かれていて、PDFファイルとしてダウンロードできる(一次情報)。
0054デフォルトの名無しさん
垢版 |
2021/06/25(金) 00:46:15.53ID:xLwe8284
解読していくと。。。
使い方を知りたいならinsns.plを読みなさいと。
拡張子.plはPerlだよな。
うわ、こんな所でPerlが出てくるのか。
0056デフォルトの名無しさん
垢版 |
2021/06/25(金) 12:06:59.81ID:W5hhXd/9
【依頼の目的と内容説明】 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]
(...続く...)
0057デフォルトの名無しさん
垢版 |
2021/06/25(金) 12:07:44.35ID:W5hhXd/9
...(続き)...
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
よろしくお願いします。
0058デフォルトの名無しさん
垢版 |
2021/06/25(金) 13:00:01.37ID:W5hhXd/9
>>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;
```
...(続く)...
0059デフォルトの名無しさん
垢版 |
2021/06/25(金) 13:01:12.12ID:W5hhXd/9
...(続き)...
```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);
```
...(続く)...
0060デフォルトの名無しさん
垢版 |
2021/06/25(金) 13:02:50.65ID:W5hhXd/9
...(続き)...
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);
```
...(続く)...
0061デフォルトの名無しさん
垢版 |
2021/06/25(金) 13:03:52.02ID:W5hhXd/9
...(続き)...
```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);
であることを鑑みると

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

```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;
}
```
となって逆コンパイルが完了する。 □
0063デフォルトの名無しさん
垢版 |
2021/06/25(金) 13:36:57.11ID:W5hhXd/9
【依頼の目的と内容説明】 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であることが分かっています。
0066デフォルトの名無しさん
垢版 |
2021/06/29(火) 20:06:52.90ID:+6dhbc6a
```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のトリック。
0069デフォルトの名無しさん
垢版 |
2021/07/14(水) 01:35:31.92ID:lv8+vNga
>>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の論理否定となる。
0070デフォルトの名無しさん
垢版 |
2021/08/03(火) 21:07:31.90ID:Q9+5cbUY
```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)) {
...
}
...
```
に書き換えることができる。
0071デフォルトの名無しさん
垢版 |
2021/08/03(火) 21:09:13.31ID:Q9+5cbUY
>>70は書き損じだから無視して。


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


```txt
if (exp) goto Label_XXXX;
...
Label_XXXX:
...
```
は、
```txt
if (!(exp)) {
...
}
...
```
に書き換えることができる。
0072デフォルトの名無しさん
垢版 |
2021/08/03(火) 21:16:45.35ID:Q9+5cbUY
ジャンプ命令は基本的に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;
```
に置き換え可能。
0074デフォルトの名無しさん
垢版 |
2021/08/04(水) 15:26:28.93ID:YCRiyQzz
```txt
if (exp)
{
...
goto Label_XXXX;
}
...
Label_XXXX:
```
は、
if (exp)
{
...
}
else
...
Label_XXXX:
```
0075デフォルトの名無しさん
垢版 |
2021/08/04(水) 15:27:12.21ID:YCRiyQzz
```txt
if (exp) {
...
goto Label_XXXX;
}
...
Label_XXXX:
```
は、
if (exp) {
...
} else {
...
}
Label_XXXX:
```
に置き換え可能。
0076デフォルトの名無しさん
垢版 |
2021/08/13(金) 14:20:39.59ID:xGO78+x4
ImmAssociateContext
ImmAssociateContextEx
ImmConfigureIMEA/W
ImmEscapeA/W
Imm32GetClientImcCache
ImmGetCompositionStringA/W
ImmGetContext
ImmInstallIMEW
ImmIsUIMessageA/W
ImmRequestMessageA/W
ImmSetCompositionStringA/W
ImmGetImeMenuItemsA/W
ImmLockIMC
ImmGenerateMessage
ImmTranslateMessage
ImmProcessKey
ImmSetActiveContext

宿題がまだこ〜んなにあるぜ。本当に全部できるのかよ。
0078デフォルトの名無しさん
垢版 |
2021/09/25(土) 20:48:50.24ID:H+l7h9ZE
とりあえず、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ビット整数。
0079デフォルトの名無しさん
垢版 |
2021/09/25(土) 20:52:28.04ID:H+l7h9ZE
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だ。
0080デフォルトの名無しさん
垢版 |
2021/09/25(土) 21:08:38.10ID:+1RCibwo
eaxの中にaxレジスタがあり、axレジスタの中にal, ahレジスタがあるという見方もできる。このような構造になっているのは16ビットとの互換性のためである。

64ビットCPUのx64、別名amd64ではrax, rbx, rcx, rdxというように、頭にrが付いた64ビットレジスタが増設された。逆工学の主な戦場はまだ32ビットにあるが、今後64ビットを対応しないといけない。
0081デフォルトの名無しさん
垢版 |
2021/09/28(火) 20:27:04.96ID:m9n91EHz
【問題】
```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
```
[=>]
0082デフォルトの名無しさん
垢版 |
2021/09/28(火) 20:29:43.46ID:m9n91EHz
```txt
edi = eax;
ecx = 0x30;
```
である。□

```asm
push (即値)
pop (レジスタX)
```
[=>]
```txt
(レジスタX) = (即値);
```
はpush-popトリックだから覚えておいてね。
0083デフォルトの名無しさん
垢版 |
2022/01/17(月) 19:44:42.22ID:32ay/bkz
今回は、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検索します。
0084デフォルトの名無しさん
垢版 |
2022/01/17(月) 19:45:19.85ID:32ay/bkz
これをDecodersTatamiに掛けてdeadfaceをgrep検索します。
main関数が見つかります。呼び出しツリーは以下のようになります。

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

というわけで、最初にFunc004010B9を解読します。
0085デフォルトの名無しさん
垢版 |
2022/01/17(月) 19:46:57.43ID:32ay/bkz
【依頼の目的と内容説明】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
```
0086デフォルトの名無しさん
垢版 |
2022/01/17(月) 19:50:05.81ID:32ay/bkz
これは非常に簡単だ。

```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;
}
```
0087デフォルトの名無しさん
垢版 |
2022/01/17(月) 19:53:15.58ID:32ay/bkz
おそらく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
0088デフォルトの名無しさん
垢版 |
2022/01/17(月) 20:00:34.53ID:32ay/bkz
解読する。

```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']
```
0089デフォルトの名無しさん
垢版 |
2022/01/17(月) 20:05:56.89ID:32ay/bkz
次の結果が得られる。

```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);
である。
0090デフォルトの名無しさん
垢版 |
2022/01/17(月) 20:06:48.16ID:32ay/bkz
よって整理すると

```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);
}
```



続きはまた明日。
0091デフォルトの名無しさん
垢版 |
2022/01/18(火) 10:34:45.36ID:kpMFjbVI
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
```
0092デフォルトの名無しさん
垢版 |
2022/01/18(火) 10:36:01.65ID:kpMFjbVI
これも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のプロトタイプは
0093デフォルトの名無しさん
垢版 |
2022/01/18(火) 10:36:31.35ID:kpMFjbVI
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);
}

0094デフォルトの名無しさん
垢版 |
2022/01/18(火) 10:45:00.41ID:kpMFjbVI
次は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トリック。
0095デフォルトの名無しさん
垢版 |
2022/01/18(火) 10:45:21.84ID:kpMFjbVI
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);

であるから、
0096デフォルトの名無しさん
垢版 |
2022/01/18(火) 10:45:51.37ID:kpMFjbVI
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);
}



続きは明日やろう。
0097デフォルトの名無しさん
垢版 |
2022/11/28(月) 18:36:01.95ID:QIQXhRT5
明日は来ない
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況