Matriochka - Step 3
Description
Can you help me?
Recently, I found an executable binary.
As I'm a true newbie,
Certainly, to solve it, I will have difficulties.
Keep in mind, the first step is quite easy.
Maybe the last one will be quite tricky.
Emulating it could be a good idea.
You must solve steps 1 and 2 first.
Details
- Points
- 300
- Category
- Crack Me
- Validations
- 90
Attachments
This challenge has no attachment.
Step2で得たBase64エンコードデータ(aaa.txtとして保存)をデコードします。
$ cat aaa.txt | tr -d '\r\n' | base64 -d > bbb
デコードしたファイルのファイルタイプをfileコマンドで確認します。Linuxの64bitバイナリです。
実行してみます。コマンドライン引数にパスワードの指定が必要であることが分かります。$ file bbb
bbb: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=2ea586c925bc94d07d2d3087837dac6ef32a180c, stripped
$ ./bbb
Usage: ./bbb <pass>
ここで、逆アセンブルして動作を解析してみます。
$ objdump -s -D bbb > ccc.txt
以下の箇所で、シグナル処理関数の登録を行っています。これにより、11:メモリアクセス違反が発生した場合、アドレス0x4007fd番地の関数が呼び出されます。また、8:浮動小数点例外が発生した場合、アドレス0x401050番地の関数が呼び出されます。
40114b: be fd 07 40 00 mov $0x4007fd,%esi #関数のアドレス
401150: bf 0b 00 00 00 mov $0xb,%edi #11:不正なメモリ参照
401155: e8 66 f5 ff ff callq 4006c0 <signal@plt> #シグナル登録
40115a: be 50 10 40 00 mov $0x401050,%esi #関数のアドレス
40115f: bf 08 00 00 00 mov $0x8,%edi #8:浮動小数点例外
401164: e8 57 f5 ff ff callq 4006c0 <signal@plt> #シグナル登録
その後、以下の箇所で繰り返しkill関数を呼び出していますが、この部分でメモリアクセス違反が発生します。したがって、0x4007fd番地の関数へ処理が移ります。
401172: 8b 45 fc mov -0x4(%rbp),%eax
401175: be 0b 00 00 00 mov $0xb,%esi
40117a: 89 c7 mov %eax,%edi
40117c: e8 5f f5 ff ff callq 4006e0 <kill@plt> #メモリアクセス違反
401181: 83 45 f8 01 addl $0x1,-0x8(%rbp) #+1
401185: 81 7d f8 ff 03 00 00 cmpl $0x3ff,-0x8(%rbp) #0x3ff=1023
40118c: 7e e4 jle 401172 <fwrite@plt+0xa72> #小さいか等しい
0x4007fd番地の関数では、0文字目のチェックを行っています。
これを逆算して0文字目を求めるRubyプログラムが以下です。実行するとDが得られます。400808: 0f b6 05 b1 38 20 00 movzbl 0x2038b1(%rip),%eax # 6040c0 <stdout+0x20>引数の文字列
40080f: 0f be c0 movsbl %al,%eax #0文字目
400812: 89 45 fc mov %eax,-0x4(%rbp)
400815: 8b 45 fc mov -0x4(%rbp),%eax
400818: 69 c8 e8 03 00 00 imul $0x3e8,%eax,%ecx #ecx=0文字目×1000
40081e: ba 79 78 78 78 mov $0x78787879,%edx #2021161081
400823: 89 c8 mov %ecx,%eax
400825: f7 ea imul %edx #edx(上位4バイト),eax(下位4バイト)=eax×0x78787879
400827: c1 fa 05 sar $0x5,%edx #edx=edx/32
40082a: 89 c8 mov %ecx,%eax #0文字目×1000
40082c: c1 f8 1f sar $0x1f,%eax #31ビット右シフト(最上位ビット)
40082f: 29 c2 sub %eax,%edx #edx=edx-eax
400831: 89 d0 mov %edx,%eax
400833: 89 45 fc mov %eax,-0x4(%rbp)
400836: 81 7d fc e7 03 00 00 cmpl $0x3e7,-0x4(%rbp) #999
40083d: 7e 09 jle 400848 <fwrite@plt+0x148> #小さいか等しい
40083f: 81 7d fc e8 03 00 00 cmpl $0x3e8,-0x4(%rbp) #1000正解
400846: 7e 02 jle 40084a <fwrite@plt+0x14a> #小さいか等しい
400848: eb 10 jmp 40085a <fwrite@plt+0x15a>
#0moij
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x78787879)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
0文字目のチェックがOKだと、以下の箇所で再度メモリアクセス違反が発生した場合のシグナルが登録されます。つまり、次にメモリアクセス違反が発生した場合は、0x40085c番地の関数が呼び出されます。
40084a: be 5c 08 40 00 mov $0x40085c,%esi #関数のアドレス
40084f: bf 0b 00 00 00 mov $0xb,%edi #11:不正なメモリ参照400854: e8 67 fe ff ff callq 4006c0 <signal@plt> #シグナル登録
retで呼び出し元に戻り、kill関数が繰り返し呼び出されますので、再度、メモリアクセス違反が発生し、0x40085c番地の関数へ処理が移ります。ここでは1文字目のチェックが行われ、OKだった場合、再度シグナルが登録されます。
同様な処理が20回ほど行われ、最終的に以下の文字列を得ることが出来ます。
実際にコマンドライン引数に指定して実行してみます。Did_you_like_signals?
$ ./bbb Did_you_like_signals?
Good good! Now let's play a game...
6ydQg8QCWEBQg+wCWMNQg8QCWEBAUIPsAljDUIPEAliDwARQg+wCWMPo1v9m6wJmLujO/8P76znr(略)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
Goodと表示されました。
したがって、フラグは、
Did_you_like_signals?
です。
以下に、0文字目から各文字のチェックを逆算するRubyプログラムを載せておきます。
#0moij
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x78787879)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#1moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x9c09c09d - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#2moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x51eb851f)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#3moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0xac769185 - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#4moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x43b3d5b)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 1
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#5moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x939a85c5 - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#6moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x8c08c08d - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#7moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0xac769185 - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#8moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x4bda12f7)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#9moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x9c09c09d - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#10moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x4c8f8d29)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#11moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x288df0cb)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 4
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#12moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0xac769185 - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#13moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x473c1ab7)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#14moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x9c09c09d - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 6
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#15moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x13e22cbd)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 3
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#16moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x94f2095 - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 2
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#17moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x151d07eb)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 3
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#18moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x4bda12f7)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#19moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x473c1ab7)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
edx = edx >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end
#20moji
for i in 32..126 do
ecx = i * 0x3e8
tmp = ecx * (0x82082083 - 0xffffffff - 1)
edx = tmp.to_s(16)[0..-9].to_i(16)
eax = tmp.to_s(16)[-8, 8].to_i(16)
eax = ecx + edx
edx = eax >> 5
eax = ecx >> 0x1f
edx = edx - eax
if edx.to_s(16).start_with?("3e8") then
print i.chr
break
end
end