LoginSignup
2
0

More than 3 years have passed since last update.

SECCON Beginners CTF 2021 解けなかった問題を勉強した記録3

Last updated at Posted at 2021-05-26

reversing 03 please_not_trace_me は gdb の勉強
reversing 04 be_angry は人生初 angr

reversing 03 please_not_trace_me

Ghidraで処理の流れを確認

main
void main(undefined4 param_1,undefined8 param_2,undefined8 param_3)

{
  int local_54;
  int local_50;
  void *local_48;
  long local_40;
  long local_38;
  undefined8 local_30;

  megaInit();
  local_30 = 9;
  _global_argv = param_2;
  _global_argc = param_1;
  _global_envp = param_3;
  do {
    switch(local_30) {
    case 0:
      local_50 = 2;
      local_30 = 0xb;
      break;
    case 2:
      local_30 = _1_main_flag_func_0(local_38,0xffffffffffffffff,0x10,5);
      break;
    case 5:
      if (local_50 == 6) {
        local_30 = 0x12;
      }
      else {
        local_30 = 8;
      }
      break;
    case 6:
      if (local_40 == 0) {
        local_30 = 0;
      }
      else {
        local_30 = 0xb;
      }
      break;
    case 8:
      fwrite("prease not trace me... ",1,0x17,stderr);
                    /* WARNING: Subroutine does not return */
      exit(1);
    case 9:
      local_54 = 0;
      local_30 = 10;
      break;
    case 10:
      switch(local_54) {
      case 0:
        local_30 = 0x16;
        break;
      case 1:
        local_30 = 0xf;
        break;
      case 2:
        local_30 = 0x13;
        break;
      case 3:
        local_30 = 0x14;
        break;
      case 4:
        local_30 = 0x11;
        break;
      case 5:
        local_30 = 0x15;
        break;
      default:
        local_30 = 0x12;
      }
      break;
    case 0xb:
      local_38 = ptrace(PTRACE_TRACEME,0,1,0);
      local_30 = 2;
      break;
    case 0xf:
      local_48 = malloc(0x10);
      local_30 = 0x12;
      break;
    case 0x10:
      local_50 = local_50 * 3;
      local_30 = 5;
      break;
    case 0x11:
      puts("flag decrypted. bye.");
      local_30 = 0x12;
      break;
    case 0x12:
      local_54 = local_54 + 1;
      local_30 = 10;
      break;
    case 0x13:
      generate_key(local_48);
      local_30 = 0x12;
      break;
    case 0x14:
      rc4(e,local_48);
      local_30 = 0x12;
      break;
    case 0x15:
                    /* WARNING: Subroutine does not return */
      exit(0);
    case 0x16:
      local_50 = 0;
      local_40 = ptrace(PTRACE_TRACEME,0,1,0);
      local_30 = 6;
    }
  } while( true );
}

local_30 で処理が分岐する
0x09 が local_30 の初期値
各分岐では,次の分岐の為に local_30 に分岐先番号を再セットしている

この再セットを gdb で細工して
0x0f malloc() # keyを格納するヒープを確保
0x13 generate_key() # keyをヒープに設定
0x14 rc4() # 復号
と処理を流せば関数名rc4(中身はrc4ではない)で復号される。
※encrypted flagは,switchに入る前のmegaInit()で設定済み。

逆アセ

gdb-peda$ pdisass main
Dump of assembler code for function main:
   0x00005555555551ff <+0>: push   rbp
   0x0000555555555200 <+1>: mov    rbp,rsp
=> 0x0000555555555203 <+4>: sub    rsp,0x70
   0x0000555555555207 <+8>: mov    DWORD PTR [rbp-0x54],edi
   0x000055555555520a <+11>:    mov    QWORD PTR [rbp-0x60],rsi
   0x000055555555520e <+15>:    mov    QWORD PTR [rbp-0x68],rdx
   0x0000555555555212 <+19>:    call   0x55555555585e <megaInit>
   0x0000555555555217 <+24>:    mov    eax,DWORD PTR [rbp-0x54]
   0x000055555555521a <+27>:    mov    DWORD PTR [rip+0x2e18],eax        # 0x555555558038 <_global_argc>
   0x0000555555555220 <+33>:    mov    rax,QWORD PTR [rbp-0x60]
   0x0000555555555224 <+37>:    mov    QWORD PTR [rip+0x2e05],rax        # 0x555555558030 <_global_argv>
   0x000055555555522b <+44>:    mov    rax,QWORD PTR [rbp-0x68]
   0x000055555555522f <+48>:    mov    QWORD PTR [rip+0x2e0a],rax        # 0x555555558040 <_global_envp>
   0x0000555555555236 <+55>:    mov    DWORD PTR [rbp-0x44],0x1
   0x000055555555523d <+62>:    mov    QWORD PTR [rbp-0x28],0x9   <--- 初期値
   0x0000555555555245 <+70>:    cmp    QWORD PTR [rbp-0x28],0x16
   0x000055555555524a <+75>:    ja     0x555555555245 <main+70>
   0x000055555555524c <+77>:    mov    rax,QWORD PTR [rbp-0x28]
   0x0000555555555250 <+81>:    lea    rdx,[rax*4+0x0]
   0x0000555555555258 <+89>:    lea    rax,[rip+0xdd5]        # 0x555555556034
   0x000055555555525f <+96>:    mov    eax,DWORD PTR [rdx+rax*1]
   0x0000555555555262 <+99>:    cdqe   
   0x0000555555555264 <+101>:   lea    rdx,[rip+0xdc9]        # 0x555555556034
   0x000055555555526b <+108>:   add    rax,rdx
   0x000055555555526e <+111>:   jmp    rax
   0x0000555555555270 <+113>:   mov    rax,QWORD PTR [rbp-0x40]
   0x0000555555555274 <+117>:   mov    rdi,rax
   0x0000555555555277 <+120>:   call   0x5555555551a9 <generate_key>
   0x000055555555527c <+125>:   mov    QWORD PTR [rbp-0x28],0x12
   0x0000555555555284 <+133>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555289 <+138>:   mov    rax,QWORD PTR [rbp-0x40]
   0x000055555555528d <+142>:   mov    rsi,rax
   0x0000555555555290 <+145>:   lea    rdi,[rip+0x2db9]        # 0x555555558050 <e>
   0x0000555555555297 <+152>:   call   0x5555555555f8 <rc4>
   0x000055555555529c <+157>:   mov    QWORD PTR [rbp-0x28],0x12
   0x00005555555552a4 <+165>:   jmp    0x5555555554b3 <main+692>
   0x00005555555552a9 <+170>:   mov    edx,DWORD PTR [rbp-0x48]
   0x00005555555552ac <+173>:   mov    eax,edx
   0x00005555555552ae <+175>:   add    eax,eax
   0x00005555555552b0 <+177>:   add    eax,edx
   0x00005555555552b2 <+179>:   mov    DWORD PTR [rbp-0x48],eax
   0x00005555555552b5 <+182>:   mov    QWORD PTR [rbp-0x28],0x5
   0x00005555555552bd <+190>:   jmp    0x5555555554b3 <main+692>
   0x00005555555552c2 <+195>:   add    DWORD PTR [rbp-0x4c],0x1
   0x00005555555552c6 <+199>:   mov    QWORD PTR [rbp-0x28],0xa
   0x00005555555552ce <+207>:   jmp    0x5555555554b3 <main+692>
   0x00005555555552d3 <+212>:   mov    DWORD PTR [rbp-0x48],0x0
   0x00005555555552da <+219>:   mov    ecx,0x0
   0x00005555555552df <+224>:   mov    edx,0x1
   0x00005555555552e4 <+229>:   mov    esi,0x0
   0x00005555555552e9 <+234>:   mov    edi,0x0
   0x00005555555552ee <+239>:   mov    eax,0x0
   0x00005555555552f3 <+244>:   call   0x555555555080 <ptrace@plt>
   0x00005555555552f8 <+249>:   mov    QWORD PTR [rbp-0x38],rax
   0x00005555555552fc <+253>:   mov    QWORD PTR [rbp-0x28],0x6
   0x0000555555555304 <+261>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555309 <+266>:   cmp    DWORD PTR [rbp-0x48],0x6
   0x000055555555530d <+270>:   je     0x55555555531c <main+285>
   0x000055555555530f <+272>:   mov    QWORD PTR [rbp-0x28],0x8
   0x0000555555555317 <+280>:   jmp    0x5555555554b3 <main+692>
   0x000055555555531c <+285>:   mov    QWORD PTR [rbp-0x28],0x12
   0x0000555555555324 <+293>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555329 <+298>:   lea    rdi,[rip+0xcd4]        # 0x555555556004
   0x0000555555555330 <+305>:   call   0x555555555040 <puts@plt>
   0x0000555555555335 <+310>:   mov    QWORD PTR [rbp-0x28],0x12
   0x000055555555533d <+318>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555342 <+323>:   mov    DWORD PTR [rbp-0x48],0x2
   0x0000555555555349 <+330>:   mov    QWORD PTR [rbp-0x28],0xb
   0x0000555555555351 <+338>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555356 <+343>:   cmp    QWORD PTR [rbp-0x38],0x0
   0x000055555555535b <+348>:   jne    0x55555555536a <main+363>
   0x000055555555535d <+350>:   mov    QWORD PTR [rbp-0x28],0x0
   0x0000555555555365 <+358>:   jmp    0x5555555554b3 <main+692>
   0x000055555555536a <+363>:   mov    QWORD PTR [rbp-0x28],0xb
   0x0000555555555372 <+371>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555377 <+376>:   cmp    DWORD PTR [rbp-0x4c],0x5
   0x000055555555537b <+380>:   ja     0x5555555553dc <main+477>
   0x000055555555537d <+382>:   mov    eax,DWORD PTR [rbp-0x4c]
   0x0000555555555380 <+385>:   lea    rdx,[rax*4+0x0]
   0x0000555555555388 <+393>:   lea    rax,[rip+0xd01]        # 0x555555556090
   0x000055555555538f <+400>:   mov    eax,DWORD PTR [rdx+rax*1]
   0x0000555555555392 <+403>:   cdqe   
   0x0000555555555394 <+405>:   lea    rdx,[rip+0xcf5]        # 0x555555556090
   0x000055555555539b <+412>:   add    rax,rdx
   0x000055555555539e <+415>:   jmp    rax
   0x00005555555553a0 <+417>:   mov    QWORD PTR [rbp-0x28],0x16
   0x00005555555553a8 <+425>:   jmp    0x5555555553e5 <main+486>
   0x00005555555553aa <+427>:   mov    QWORD PTR [rbp-0x28],0xf
   0x00005555555553b2 <+435>:   jmp    0x5555555553e5 <main+486>
   0x00005555555553b4 <+437>:   mov    QWORD PTR [rbp-0x28],0x13
   0x00005555555553bc <+445>:   jmp    0x5555555553e5 <main+486>
   0x00005555555553be <+447>:   mov    QWORD PTR [rbp-0x28],0x14
   0x00005555555553c6 <+455>:   jmp    0x5555555553e5 <main+486>
   0x00005555555553c8 <+457>:   mov    QWORD PTR [rbp-0x28],0x11
   0x00005555555553d0 <+465>:   jmp    0x5555555553e5 <main+486>
   0x00005555555553d2 <+467>:   mov    QWORD PTR [rbp-0x28],0x15
   0x00005555555553da <+475>:   jmp    0x5555555553e5 <main+486>
   0x00005555555553dc <+477>:   mov    QWORD PTR [rbp-0x28],0x12
   0x00005555555553e4 <+485>:   nop
   0x00005555555553e5 <+486>:   jmp    0x5555555554b3 <main+692>
   0x00005555555553ea <+491>:   mov    rax,QWORD PTR [rip+0x2c2f]        # 0x555555558020 <stderr@@GLIBC_2.2.5>
   0x00005555555553f1 <+498>:   mov    rcx,rax
   0x00005555555553f4 <+501>:   mov    edx,0x17
   0x00005555555553f9 <+506>:   mov    esi,0x1
   0x00005555555553fe <+511>:   lea    rdi,[rip+0xc14]        # 0x555555556019
   0x0000555555555405 <+518>:   call   0x5555555550a0 <fwrite@plt>
   0x000055555555540a <+523>:   mov    edi,0x1
   0x000055555555540f <+528>:   call   0x555555555090 <exit@plt>
   0x0000555555555414 <+533>:   mov    edi,0x0
   0x0000555555555419 <+538>:   call   0x555555555090 <exit@plt>
   0x000055555555541e <+543>:   mov    QWORD PTR [rbp-0x18],0x10
   0x0000555555555426 <+551>:   mov    QWORD PTR [rbp-0x10],0x5
   0x000055555555542e <+559>:   mov    rcx,QWORD PTR [rbp-0x10]
   0x0000555555555432 <+563>:   mov    rdx,QWORD PTR [rbp-0x18]
   0x0000555555555436 <+567>:   mov    rax,QWORD PTR [rbp-0x30]
   0x000055555555543a <+571>:   mov    rsi,0xffffffffffffffff
   0x0000555555555441 <+578>:   mov    rdi,rax
   0x0000555555555444 <+581>:   call   0x555555555933 <_1_main_flag_func_0>
   0x0000555555555449 <+586>:   mov    QWORD PTR [rbp-0x8],rax
   0x000055555555544d <+590>:   mov    rax,QWORD PTR [rbp-0x8]
   0x0000555555555451 <+594>:   mov    QWORD PTR [rbp-0x28],rax
   0x0000555555555455 <+598>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555457 <+600>:   mov    DWORD PTR [rbp-0x4c],0x0
   0x000055555555545e <+607>:   mov    QWORD PTR [rbp-0x28],0xa
   0x0000555555555466 <+615>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555468 <+617>:   mov    ecx,0x0
   0x000055555555546d <+622>:   mov    edx,0x1
   0x0000555555555472 <+627>:   mov    esi,0x0
   0x0000555555555477 <+632>:   mov    edi,0x0
   0x000055555555547c <+637>:   mov    eax,0x0
   0x0000555555555481 <+642>:   call   0x555555555080 <ptrace@plt>
   0x0000555555555486 <+647>:   mov    QWORD PTR [rbp-0x30],rax
   0x000055555555548a <+651>:   mov    QWORD PTR [rbp-0x28],0x2
   0x0000555555555492 <+659>:   jmp    0x5555555554b3 <main+692>
   0x0000555555555494 <+661>:   mov    edi,0x10
   0x0000555555555499 <+666>:   call   0x555555555070 <malloc@plt>
   0x000055555555549e <+671>:   mov    QWORD PTR [rbp-0x20],rax
   0x00005555555554a2 <+675>:   mov    rax,QWORD PTR [rbp-0x20]
   0x00005555555554a6 <+679>:   mov    QWORD PTR [rbp-0x40],rax
   0x00005555555554aa <+683>:   mov    QWORD PTR [rbp-0x28],0x12
   0x00005555555554b2 <+691>:   nop
   0x00005555555554b3 <+692>:   jmp    0x555555555245 <main+70>
End of assembler dump.

switchで分岐させている local_30 は,QWORD PTR [rbp-0x28] に格納される

初期値 0x9 が入っている状況

gdb-peda$ x/x $rbp-0x28
0x7fffffffe218: 0x0000000000000009

スタックのアドレスは 0x7fffffffe218

0x7fffffffe218の値をタイミングよく,0x09 --> 0x0f --> 0x13 --> 0x14 と書き換えながら n (next) で進める

case 0x9 の分岐で,次の値を 0x0f に書き換えて n (next)

gdb-peda$ set {int}0x7fffffffe218=0x0f

case 0x0f の分岐で,mallocを通過後, 0x13 に書き換えて n (next)

=> 0x555555555499 <main+666>:   call   0x555555555070 <malloc@plt>

gdb-peda$ set {int}0x7fffffffe218=0x13

case 0x13 の分岐で,generate_keyを通過後, 0x14 に書き換えて n (next)

=> 0x555555555277 <main+120>:   call   0x5555555551a9 <generate_key>

gdb-peda$ set {int}0x7fffffffe218=0x14

復号処理に入ってくる

=> 0x555555555297 <main+152>:   call   0x5555555555f8 <rc4>

rc4を抜けたところで, RAX (ret) を確認
image.png

後の祭りというか,結果論というか,このくらい,gdbでメモリを書き換えたこと一度もなかったにせよ,当日できそうだ。
ふがいない自分に腹が立つ。

reversing 04 be_angry

今日,初めて angr のインストールに成功したので angr問題に挑戦する。

普通に動かすと

# ./be_angry
AAA
Incorrect!!

Ghidraのデコンパイル

main

void main(undefined4 param_1,undefined8 param_2,undefined8 param_3)

{
  uint uVar1;
  int iVar2;
  long in_FS_OFFSET;
  uint local_190;
  long local_160;
  char local_38 [2];
  char local_36;
  char local_34;
  char local_32;
  char local_2f;
  char local_2d;
  char local_2b;
  char local_2a;
  char local_28;
  char local_27;
  char local_25;
  char local_22;
  char local_21;
  undefined8 local_10;

  local_10 = *(undefined8 *)(in_FS_OFFSET + 0x28);
  megaInit();
  local_160 = 0xe;
  _global_argv = param_2;
  _global_argc = param_1;
  _global_envp = param_3;
  do {
                    /* WARNING: Could not find normalized switch variable to match jumptable */
    switch(local_160) {
    case 0:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 2:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 4:
      if ((int)((int)local_22 - (local_190 * 2 + ~local_190) |
               (~local_190 + local_190 * 2) - (int)local_22) < 0) {
        local_160 = 10;
      }
      else {
        local_160 = 0x10;
      }
      break;
    case 6:
      if ((int)((int)local_27 - (local_190 + 4) | (local_190 + 4) - (int)local_27) < 0) {
        local_160 = 5;
      }
      else {
        local_160 = 0xd;
      }
      break;
    case 8:
      iVar2 = -((int)((((int)local_2f - ((local_190 & 0xffffffcc) * 2 + (local_190 ^ 0xffffffcc))) +
                       0x80000000 ^
                      (int)(((int)local_2f -
                            ((local_190 & 0xffffffcc) * 2 + (local_190 ^ 0xffffffcc))) + -0x80000000
                           ) >> 0x1f) -
                     ((int)(((int)local_2f -
                            ((local_190 & 0xffffffcc) * 2 + (local_190 ^ 0xffffffcc))) + -0x80000000
                           ) >> 0x1f)) >> 0x1f);
      uVar1 = (uint)(iVar2 == 0);
      local_160 = ((long)(int)~uVar1 & 0xcU) * (long)(int)uVar1 + (long)iVar2 * 0x21;
      break;
    case 10:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0xc:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0xe:
      local_190 = 100;
      fgets(local_38,0x19,stdin);
      local_160 = 0x28;
      break;
    case 0x10:
      if ((int)((((int)local_21 - ((local_190 & 0x19) * 2 + (local_190 ^ 0x19))) + 0x80000000 ^
                (int)(((int)local_21 - ((local_190 & 0x19) * 2 + (local_190 ^ 0x19))) + -0x80000000)
                >> 0x1f) -
               ((int)(((int)local_21 - ((local_190 & 0x19) * 2 + (local_190 ^ 0x19))) + -0x80000000)
               >> 0x1f)) < 0) {
        local_160 = 0x20;
      }
      else {
        local_160 = 0x1a;
      }
      break;
    case 0x12:
      local_160 = _1_main_flag_func_6((int)local_2d,local_190 - 0x31,0x19);
      break;
    case 0x14:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x16:
      local_160 = _1_main_flag_func_3((int)local_2b,local_190 - 0x30,0x2a);
      break;
    case 0x18:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x1a:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x1c:
      if ((int)((int)local_32 - ((local_190 * 2 | 0xffffff9e) - (local_190 ^ 0xffffffcf)) |
               ((local_190 * 2 | 0xffffff9e) - (local_190 ^ 0xffffffcf)) - (int)local_32) < 0) {
        local_160 = 9;
      }
      else {
        local_160 = 0x29;
      }
      break;
    case 0x1e:
      local_160 = _1_main_flag_func_2((int)local_36,(local_190 | 2) * 2 - (local_190 ^ 2),0x15);
      break;
    case 0x20:
      puts("Correct!!");
      local_160 = 0x27;
      break;
    case 0x22:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x24:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x26:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x28:
      if ((int)((int)local_38[0] - (local_190 - 1) | (local_190 - 1) - (int)local_38[0]) < 0) {
        local_160 = 0x2f;
      }
      else {
        local_160 = 0xb;
      }
      break;
    case 0x2a:
      if ((int)(((int)local_2a - ((local_190 * 2 | 0x1c) - (local_190 ^ 0xe)) ^
                (int)((int)local_2a - ((local_190 * 2 | 0x1c) - (local_190 ^ 0xe))) >> 0x1f) -
               ((int)((int)local_2a - ((local_190 * 2 | 0x1c) - (local_190 ^ 0xe))) >> 0x1f)) < 1) {
        local_160 = 3;
      }
      else {
        local_160 = 2;
      }
      break;
    case 0x2c:
      puts("Incorrect!!");
      local_160 = 0x27;
      break;
    case 0x2e:
      iVar2 = -((int)((((int)local_34 - (local_190 - 2) ^
                       (int)((int)local_34 - (local_190 - 2)) >> 0x1f) -
                      ((int)((int)local_34 - (local_190 - 2)) >> 0x1f)) + -1) >> 0x1f);
      local_160 = (long)(int)(uint)(iVar2 == 0) * 0x11 + (long)iVar2 * 0x31;
      break;
    case 0x30:
      if ((int)((int)local_28 - ((local_190 | 0x10) * 2 + (local_190 ^ 0xffffffef) + 1) |
               ((local_190 | 0x10) * 2 + (local_190 ^ 0xffffffef) + 1) - (int)local_28) < 0) {
        local_160 = 0x23;
      }
      else {
        local_160 = 6;
      }
      break;
    case 0x32:
      iVar2 = -((int)(((int)((int)local_25 -
                            ((local_190 * 2 & 0xffffff9e) + (local_190 ^ 0xffffffcf))) >> 0x1f ^
                      ((int)local_25 - ((local_190 * 2 & 0xffffff9e) + (local_190 ^ 0xffffffcf))) +
                      ((int)((int)local_25 -
                            ((local_190 * 2 & 0xffffff9e) + (local_190 ^ 0xffffffcf))) >> 0x1f)) - 1
                     ) >> 0x1f);
      local_160 = ((long)(int)(uint)(iVar2 == 0) * 0x1f & (long)iVar2 * 0x17) * 2 +
                  ((long)iVar2 * 0x17 ^ (long)(int)(uint)(iVar2 == 0) * 0x1f);
    }
  } while( true );
}

正解の特徴的な文字 "Correct!!" を使って,angr する。
コードは作問者writeup

実行結果

# workon angr
(angr) ~# python3 be_angry.py 
WARNING | 2021-05-26 20:07:00,429 | cle.loader | The main binary is a position-independent executable. It is being loaded with a base address of 0x400000.
ctf4b{3nc0d3_4r1thm3t1c}
(angr) ~# deactivate
# 

すごいな。 angr

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0