BuringStraw

BuringStraw

Junk_Instruction(2019_西湖論剣_予選)

問題:xctf

MFC プログラムで、ウィンドウ情報を xspy で表示します。

チェックボタンの ID は 03e9 で、同時にウィンドウにOnCommand: notifycode=0000 id=03e9,func= 0x00C72420(Junk_Instruction.exe+ 0x002420 )という関数が存在します。

その関数(sub_402420)に入ると、条件分岐があります:if ( (unsigned __int8)sub_402600(v2 + 16) )。2 つの分岐はそれぞれ正しいダイアログと間違ったダイアログを表示するため、sub_402600は検証関数であることがわかります。

この関数には多くのジャンク命令が含まれています。まず、呼び出しのために戻りアドレスをスタックにプッシュし、それからスタックから戻りアドレスをポップして変更し、再度プッシュします。すると、戻りアドレスが変わります。

.text:0040293F E8 00 00 00 00                call    $+5
.text:0040293F
.text:00402944
.text:00402944                               loc_402944:                             ; DATA XREF: sub_402600+398↓r
.text:00402944 58                            pop     eax
.text:00402945 89 85 C4 FD FF FF             mov     [ebp+var_23C], eax
.text:0040294B E8 03 00 00 00                call    loc_402953
.text:0040294B
.text:0040294B                               ; ---------------------------------------------------------------------------
.text:00402950 EA                            db 0EAh
.text:00402951                               ; ---------------------------------------------------------------------------
.text:00402951 EB 09                         jmp     short loc_40295C
.text:00402951
.text:00402953                               ; ---------------------------------------------------------------------------
.text:00402953
.text:00402953                               loc_402953:                             ; CODE XREF: sub_402600+34B↑j
.text:00402953 5B                            pop     ebx
.text:00402954 43                            inc     ebx
.text:00402955 53                            push    ebx
.text:00402956 B8 11 11 11 11                mov     eax, 11111111h
.text:0040295B C3                            retn
.text:0040295C                               ; ---------------------------------------------------------------------------
.text:0040295C
.text:0040295C                               loc_40295C:                             ; CODE XREF: sub_402600+351↑j
.text:0040295C E8 07 00 00 00                call    loc_402968
.text:0040295C
.text:00402961 BB 33 33 33 33                mov     ebx, 33333333h
.text:00402966 EB 0D                         jmp     short loc_402975
.text:00402966
.text:00402968                               ; ---------------------------------------------------------------------------
.text:00402968
.text:00402968                               loc_402968:                             ; CODE XREF: sub_402600:loc_40295C↑p
.text:00402968 BB 11 11 11 11                mov     ebx, 11111111h
.text:0040296D 5B                            pop     ebx
.text:0040296E BB 75 29 40 00                mov     ebx, offset loc_402975
.text:00402973 53                            push    ebx
.text:00402974 C3                            retn

これらのジャンク命令は複雑な分岐構造を持っていませんが、次のセクションにジャンプするだけなので、すべてnopで置き換えれば問題ありません。

2AF0、2CA0、2e80 の関数も同様です。デコンパイルしてみると、それぞれの機能はフラグを削除し、括弧を反転させ、RC4 の初期化、RC4 の暗号化です。その後、ループがあり、暗号文が正しいかどうかを比較します。

暗号文は 2600 で始まる長い代入文(5bD6D026C8DD197E6E3ECB16917DFFAFDD7664B0F7E58957829F0C009ED045FA)であり、パスワードはqwertyuiopです。

これを CyberChef に入力すれば結果が得られます。反転することを忘れずに、フラグ {} を付けることも忘れずに。


PS:

最初はすべての命令をnopで置き換えるのは怖くてできませんでした。eax と ebx に値が代入されているので、それらが重要なものかもしれないと心配していました。結果として、たくさんの JMP が残ってしまいました。ida: 6。後で大先輩の花削除スクリプトを見たら、直接nopで置き換えていました...。そのスクリプトは Python 2 用だったので、Python 3 用に変更しました。

from ida_bytes import get_bytes, patch_bytes
import re
addr = 0x402600
end = 0x402ae3
buf = get_bytes(addr, end-addr)
def handler1(s):
    s = s.group(0)
    print("".join(["%02x"%i for i in s]))
    s = b"\x90"*len(s)
    return s
p = b"\xe8\x00\x00\x00\x00.*?\xc3.*?\xc3"
buf = re.sub(p, handler1, buf, flags=re.I)
patch_bytes(addr, buf)
print("Done")

ただ、このマッチングは少し問題があるようで、RC4 の暗号化関数が多くのnopで置き換えられてしまいます。したがって、上記の範囲は sub_402600 に限定しています。(RC4 の暗号化が予想される場合は影響はありません)。


最初は MFC に詳しいと思っていましたが、全くわからず、xspy というものを知ったのは今です。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。