llvm的题,就是用一系列数字表示一个执行顺序,把代码一行行插到里边。安上不angr,因为这个题代码少,可以手工分析。
主程序就俩分支,顺序一看就明白,先给个数独应该是输入填的空;然后check
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
__int64 v4; // rsi
int i; // [rsp+2Ch] [rbp-54h]
unsigned int v7; // [rsp+38h] [rbp-48h]
char v8[56]; // [rsp+40h] [rbp-40h] BYREF
int v9; // [rsp+78h] [rbp-8h]
int v10; // [rsp+7Ch] [rbp-4h]
v9 = 0;
printf("input your flag:");
gets(v8, argv);
v10 = general_inspection((int (*)[9])sudoku);
for ( i = 2490451983; ; i = -303742386 )
{
while ( 1 )
{
while ( i == -2071121728 )
{
v7 = blank_num((int (*)[9])sudoku);
v4 = mem_alloc(v7);
trace(sudoku, v4, v7);
check((int (*)[9])sudoku); // 空
check1(v8); // 3步处理
check3(v8); // 数据核对
v9 = 0;
i = -303742386;
}
if ( i != -1804515313 )
break;
v3 = -2071121728;
if ( v10 )
v3 = 664169471;
i = v3;
}
if ( i == -303742386 )
break;
printf("error");
check((int (*)[9])sudoku);
v9 = 0;
}
return v9;
}
第1个check啥也没作(略)
第2个进行3步处理第1步将奇偶位交换,第2步将前一半与后一半交换,第3步就是第3,4位取反再减20,这个可以简化为^0xc -20
a1[v12] = (a1[v12] & 0xF3 | ~a1[v12] & 0xC) - 20;// ^0xc -20
数独这块手工解,不过是多解。用8在前的(程序试数一般从小试)
data = open('attachment', 'rb').read()[0x4060: 0x4060+81*4]
for i in range(9):
for j in range(9):
print(data[4*(i*9+j)], end='')
print('')
'''
105327008
809050020
070010503
490100300
010070906
703290480
060540809
004001030
021030704
'''
#4693641762894685722843556137219876255986
#4693641762984685722843556137219876255896
s = b'4693641762894685722843556137219876255986'
#3 v^0xc -20
s = [(i+20)^0xc for i in s]
#2 right+left
s = s[20:]+s[:20]
#1 odd+even
for i in range(0,40,2):
s[i],s[i+1] = s[i+1],s[i]
print(bytes(s))
#flag{KDEEIFGKIJ@AFGEJAEF@FDKADFGIJFA@FDE@JG@J}