- Source: Daily AlpacaHack
- Author: chokorusk
フラグチェッカーのような動作を行うバイナリが配布される。
Ghidraでデコンパイルしてmain関数を読む。
undefined8 main(void)
{
char cVar1;
int iVar2;
undefined8 uVar3;
long in_FS_OFFSET;
long local_188;
ulong local_180;
undefined1 local_178 [176];
char local_c8 [48];
char local_98 [136];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_188 = 0;
printf("flag: ");
cVar1 = read_flag_input(local_98,0x80,&local_188);
if (cVar1 == '\x01') {
if (local_188 == 0x20) {
local_c8[0] = -0x52;
local_c8[1] = '=';
local_c8[2] = '\x10';
local_c8[3] = 'l';
local_c8[4] = -0x4c;
local_c8[5] = -0x7e;
local_c8[6] = '\x10';
local_c8[7] = -0x75;
local_c8[8] = -0x61;
local_c8[9] = 'z';
local_c8[10] = -0x37;
local_c8[0xb] = '\x01';
local_c8[0xc] = -0x52;
local_c8[0xd] = -0x69;
local_c8[0xe] = -0x5e;
local_c8[0xf] = -0x50;
local_c8[0x10] = '@';
local_c8[0x11] = '/';
local_c8[0x12] = 'J';
local_c8[0x13] = -0x5b;
local_c8[0x14] = -0x2a;
local_c8[0x15] = '+';
local_c8[0x16] = 'B';
local_c8[0x17] = '<';
local_c8[0x18] = -0x34;
local_c8[0x19] = '~';
local_c8[0x1a] = -0x41;
local_c8[0x1b] = -0x5c;
local_c8[0x1c] = '\x14';
local_c8[0x1d] = -0x7d;
local_c8[0x1e] = -0x7d;
local_c8[0x1f] = '3';
init_cipher(local_178,key);
for (local_180 = 0; local_180 < 0x20; local_180 = local_180 + 0x10) {
decrypt_block(local_178,local_c8 + local_180);
}
local_c8[0x20] = 0;
iVar2 = strcmp(local_98,local_c8);
if (iVar2 == 0) {
puts("correct!");
}
else {
puts("wrong...");
}
uVar3 = 0;
}
else {
puts("wrong...");
uVar3 = 0;
}
}
else {
uVar3 = 1;
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return uVar3;
}
本質はここで、入力の長さが32の時、decryptしたflagと思しき文字列をstrcmpで比較している。
if (local_188 == 0x20) {
local_c8[0] = -0x52;
...(略)
local_c8[0x1f] = '3';
init_cipher(local_178,key);
for (local_180 = 0; local_180 < 0x20; local_180 = local_180 + 0x10) {
decrypt_block(local_178,local_c8 + local_180);
}
local_c8[0x20] = 0;
iVar2 = strcmp(local_98,local_c8);
strcmpを実行する時点でlocal_c8にはflagが入っていることが期待できるので、これを動的解析で抜き取る。
今回はltraceコマンドを使用し、適当な32文字の文字列を入力することでメモリ上に復元されたflagを確認できた。
$ ltrace -e strcmp ./chal
flag: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
chal->strcmp("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., "Alpaca{m3ccha_rand0m_5b0x_d4yo!}"...) = 32
wrong...
+++ exited (status 0) +++
Alpaca{m3ccha_rand0m_5b0x_d4yo!}