reversing 03 please_not_trace_me は gdb の勉強
reversing 04 be_angry は人生初 angr
reversing 03 please_not_trace_me
Ghidraで処理の流れを確認
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>
後の祭りというか,結果論というか,このくらい,gdbでメモリを書き換えたこと一度もなかったにせよ,当日できそうだ。
ふがいない自分に腹が立つ。
reversing 04 be_angry
今日,初めて angr のインストールに成功したので angr問題に挑戦する。
普通に動かすと
# ./be_angry
AAA
Incorrect!!
Ghidraのデコンパイル
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