Ghidraのデコンパイル誤りを訂正する訓練になるので記録に残しておく。
問題の入手先
問題としては,ELFバイナリ「mystery」と PNG画像「mystery.png」「mystery2.png」「mystery3.png」が渡される。
PNGを確認すると,フッターの後にフラグらしきものが見える。
Ghidraでデコンパイルしてみる
mystery
void main(void)
{
FILE *__stream;
FILE *__stream_00;
FILE *__stream_01;
FILE *__stream_02;
long in_FS_OFFSET;
char local_6b;
int local_68;
int local_64;
int local_60;
char local_38 [4];
char local_34;
char local_33;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
__stream = fopen("flag.txt","r");
__stream_00 = fopen("mystery.png","a");
__stream_01 = fopen("mystery2.png","a");
__stream_02 = fopen("mystery3.png","a");
if (__stream == (FILE *)0x0) {
puts("No flag found, please make sure this is run on the server");
}
if (__stream_00 == (FILE *)0x0) {
puts("mystery.png is missing, please run this on the server");
}
fread(local_38,0x1a,1,__stream);
fputc((int)local_38[1],__stream_02);
fputc((int)(char)(local_38[0] + '\x15'),__stream_01);
fputc((int)local_38[2],__stream_02);
local_6b = local_38[3];
fputc((int)local_33,__stream_02);
fputc((int)local_34,__stream_00);
local_68 = 6;
while (local_68 < 10) {
local_6b = local_6b + '\x01';
fputc((int)local_38[local_68],__stream_00);
local_68 = local_68 + 1;
}
fputc((int)local_6b,__stream_01);
local_64 = 10;
while (local_64 < 0xf) {
fputc((int)local_38[local_64],__stream_02);
local_64 = local_64 + 1;
}
local_60 = 0xf;
while (local_60 < 0x1a) {
fputc((int)local_38[local_60],__stream_00);
local_60 = local_60 + 1;
}
fclose(__stream_00);
fclose(__stream);
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
真っ先に気になる点
char local_38 [4];
fread(local_38,0x1a,1,__stream);
0x1a を読み込むのに char[4]はないよね
local_38 の型を char[26] に
変数名については
local_38 を flag に
__stream_00 を __stream_p1 に
__stream_01 を __stream_p2 に
__stream_02 を __stream_p3 に
local_68 を i に
local_64 を j に
local_60 を k に
local_6b を temp に
mystery
void main(void)
{
long lVar1;
FILE *__stream;
FILE *__stream_p1;
FILE *__stream_p2;
FILE *__stream_p3;
long in_FS_OFFSET;
char temp;
int i;
int j;
int k;
char flag [26];
lVar1 = *(long *)(in_FS_OFFSET + 0x28);
__stream = fopen("flag.txt","r");
__stream_p1 = fopen("mystery.png","a");
__stream_p2 = fopen("mystery2.png","a");
__stream_p3 = fopen("mystery3.png","a");
if (__stream == (FILE *)0x0) {
puts("No flag found, please make sure this is run on the server");
}
if (__stream_p1 == (FILE *)0x0) {
puts("mystery.png is missing, please run this on the server");
}
fread(flag,0x1a,1,__stream);
fputc((int)flag[1],__stream_p3);
fputc((int)(char)(flag[0] + '\x15'),__stream_p2);
fputc((int)flag[2],__stream_p3);
temp = flag[3];
fputc((int)flag[5],__stream_p3);
fputc((int)flag[4],__stream_p1);
i = 6;
while (i < 10) {
temp = temp + '\x01';
fputc((int)flag[i],__stream_p1);
i = i + 1;
}
fputc((int)temp,__stream_p2);
j = 10;
while (j < 0xf) {
fputc((int)flag[j],__stream_p3);
j = j + 1;
}
k = 0xf;
while (k < 0x1a) {
fputc((int)flag[k],__stream_p1);
k = k + 1;
}
fclose(__stream_p1);
fclose(__stream);
if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
デコンパイル結果がソースコードに近くなったところでソルバー作成
png1 = list("CF{An1_e2630725}")
png2 = list("\x85s")
png3 = list("icT0tha_")
ans = [0] * 0x1a
# png3
ans[1] = png3[0]
ans[2] = png3[1]
ans[5] = png3[2]
j = 10
while j < 0xf:
ans[j] = png3[j-7]
j = j + 1
# png2
ans[0] = chr(ord(png2[0]) - 0x15)
temp = png2[1]
# png1
ans[4] = png1[0]
i = 6
while i < 10:
temp = chr(ord(temp) - 0x1)
ans[i] = png1[i-5]
i = i + 1
k = 0xf
while k < 0x1a:
ans[k] = png1[k-10]
k = k + 1
ans[3] = temp
# print(ans)
print(''.join(ans))
※ソルバーに全角文字が混じっていました。(2021/4/20訂正)