1. ホーム
  2. unix

[解決済み] バイナリーボム フェーズ2

2022-02-12 13:45:51

質問

このアセンブリコードが1,2,6,24,120,720の6つの数字を表示するのかしないのか、非常に困っているのです。GDBで何度も試してみましたが、eaxの値が1,2,3,6と変動し、何らかの理由で2回以上ループしないことがわかりました。私は本当にこれに行き詰っています。これは、他のバイナリボムフェーズ2の投稿とは異なるため、関係ありません。

0x000000000040129f <+0>:        push   %rbp
0x00000000004012a0 <+1>:        push   %rbx
0x00000000004012a1 <+2>:        sub    $0x28,%rsp
0x00000000004012a5 <+6>:        mov    %rsp,%rsi
0x00000000004012a8 <+9>:        callq  0x40185a <read_six_numbers>
0x00000000004012ad <+14>:       cmpl   $0x1,(%rsp)
0x00000000004012b1 <+18>:       je     0x4012be <phase_2+31>
0x00000000004012b3 <+20>:       mov    $0x0,%eax
0x00000000004012b8 <+25>:       callq  *0x2034e2(%rip)        # <explode>
0x00000000004012be <+31>:       mov    %rsp,%rbx
0x00000000004012c1 <+34>:       mov    $0x1,%ebp
0x00000000004012c6 <+39>:       mov    (%rbx),%eax
0x00000000004012c8 <+41>:       lea    (%rax,%rax,2),%eax
0x00000000004012cb <+44>:       mov    %eax,%edx
0x00000000004012cd <+46>:       xor    0x4(%rbx),%edx
0x00000000004012d0 <+49>:       mov    %ebp,%ecx
0x00000000004012d2 <+51>:       sar    %cl,%eax
0x00000000004012d4 <+53>:       cmp    %eax,%edx
0x00000000004012d6 <+55>:       je     0x4012e3 <phase_2+68>
0x00000000004012d8 <+57>:       mov    $0x0,%eax
0x00000000004012dd <+62>:       callq  *0x2034bd(%rip)       <explode>
0x00000000004012e3 <+68>:       add    $0x1,%ebp
0x00000000004012e6 <+71>:       add    $0x4,%rbx
0x00000000004012ea <+75>:       cmp    $0x6,%ebp
0x00000000004012ed <+78>:       jne    0x4012c6 <phase_2+39>
0x00000000004012ef <+80>:       add    $0x28,%rsp
0x00000000004012f3 <+84>:       pop    %rbx
0x00000000004012f4 <+85>:       pop    %rbp
0x00000000004012f5 <+86>:       retq  

これが、レジスタの2回目の繰り返しで得られたものです。raxとrdxは等しくないので、最後のジャンプは実行されませんので、次の反復はありません。これは、6つの数字が現れるまでループバックすることができるはずだと思うので、私を困惑させています。

rax            0x1  1
rbx            0x7fffffffe1f4   140737488347636
rcx            0x2  2
rdx            0x5  5
rsi            0x402e7d 4206205
rdi            0x7fffffffdb21   140737488345889
rbp            0x2  0x2
rsp            0x7fffffffe1f0   0x7fffffffe1f0
r8             0x3e9258ee40 268743274048
r9             0x100    256
r10            0xb  11
r11            0xb  11
r12            0x400e30 4197936
r13            0x7fffffffe320   140737488347936
r14            0x0  0
r15            0x0  0
rip            0x4012d8 0x4012d8 <phase_2+57>
eflags         0x202    [ IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0

解決方法は?

と判断されたのですね。

  • 最初の数値は1
  • 数字を反復するループがあります。
  • 真でなければならない条件がある

ループを見てみましょう。明らかなように ebp はカウンタで rbx は数字を通過するポインタである。

さて、条件です。2つのオペランドはどのように設定されるのでしょうか?というと eax から読み込まれていることがわかります。 (%rbx) が現在の数であり、それに対して何らかの演算が行われる。最初の数字がわかっているので、結果を変更することはできないので、何をするのかはあまり気にしない。

もう一方のオペランドは edx . これも何らかの方法で現在の数値から計算されますが、これも xor は、次の番号で-される(その xor 0x4(%rbx),%edx の行)になります。

これらの情報をもとに、次のように入力します。 1 0 0 0 0 0 を最初の推測とします。ちなみに xor0 は数字を変更せずに残します。比較までプログラムを走らせ、中身を確認する eaxedx . それは、次のようになります。 13 であり、残念ながら等しくはありません。上で述べたように、私たちは eax を変更することができます。 edx を次の数字とxorすることで実現できます。そのため xor が動作します。 eax ^ edx が次の番号になります。gdbに次のように表示させることができます。 p $eax ^ $edx . さて、プログラムを再起動し、最初のゼロのプレースホルダーの代わりにこの数字を入力します。ループをもう一回繰り返し、残りの数字を得るためにこの処理を繰り返してください。