フラグを復号してくれるのは良いけど,表示してくれない!!
とりあえずGhidraで開きます
void main(int argc,char **argv,char **envp)
{
int local_54;
int local_50;
char *local_48;
long local_40;
long local_38;
long local_30;
megaInit();
local_30 = 9;
_global_argv = argv;
_global_argc = argc;
_global_envp = envp;
do {
switch(local_30) {
case 0:
local_50 = 2;
local_30 = 0xb;
break;
case 2:
local_30 = _1_main_flag_func_0(local_38,-1,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...\n",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 = (char *)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 );
}
rc4でフラグを復号したあと、そのアドレスをそのまま破棄しているようです
rc4の後に実行フローの制御に用いている変数の代入処理があるので、かわりに復号した値を出力する処理にすりかえてしまえばflagが得られそうです
ということでRC4の処理を行なった直後のアドレスである0x129c
をCutterで開きます
そして、そこで編集→Instructionsで以下のアセンブリにすりかえます
mov rdi, rax ;
call 0x1040 ;
0x1040はsym.imp.puts
のアドレスです
実行するとflagの表示処理が無限ループで回ります
ctf4b{d1d_y0u_d3crypt_rc4?}