是一个64位程序,拿到题目放入IDA中分析,一堆函数没找到主函数。题目提示又是gogogo就想到了最近常听到的go语言。查了一下资料知道找不到main函数的go语言程序,是无符号的。为了方便分析使用脚本IDAGolangHelper-master去符号信息还原。
ALT+F7引用这个脚本,出现如下界面,前面两个检测版本,检测出为1.8 or 1.9 or 1.10
选择一下下面的版本,把剩余三个按钮全点一遍之后 点ok以后就能将各个函数分析出来,并且能找到主函数。
来到主函数
__int64 __fastcall main_main(__int64 a1, __int64 a2)
{
__int64 v2; // r8
__int64 v3; // r9
__int64 v4; // r8
__int64 v5; // r9
__int64 v6; // rdx
__int64 v7; // rcx
__int64 v8; // r8
__int64 v9; // r9
__int128 v10; // ST00_16
__int64 v11; // ST18_8
int v12; // er8
__int64 v13; // r8
__int64 v14; // r9
__int64 result; // rax
const __m128i *v16; // rdx
__int64 v17; // r8
__int64 v18; // r9
char v19; // ST18_1
__int64 v20; // rdx
__int64 v21; // r8
__int64 v22; // r9
__int64 v23; // [rsp+8h] [rbp-F8h]
char v24; // [rsp+58h] [rbp-A8h]
char v25; // [rsp+80h] [rbp-80h]
const __m128i *v26; // [rsp+98h] [rbp-68h]
__int64 v27; // [rsp+A0h] [rbp-60h]
__int128 v28; // [rsp+A8h] [rbp-58h]
__int128 v29; // [rsp+B8h] [rbp-48h]
__int128 v30; // [rsp+C8h] [rbp-38h]
__int128 v31; // [rsp+D8h] [rbp-28h]
__int128 v32; // [rsp+E8h] [rbp-18h]
if ( (unsigned __int64)&v25 <= *(_QWORD *)(__readfsqword(0xFFFFFFF8) + 16) )
runtime_morestack_noctxt(a1, a2);
runtime_newobject(a1, a2);
v27 = v23;
*(_QWORD *)&v32 = &unk_4A6D00;
*((_QWORD *)&v32 + 1) = &off_4E1130;
fmt_Fprintln(a1, a2, (__int64)&v32, (__int64)&unk_4A6D00, v2, v3, (__int64)&off_4E28A0, qword_572B18);
*(_QWORD *)&v31 = &unk_4A3E80;
*((_QWORD *)&v31 + 1) = v27;
fmt_Fscanf(
a1,
a2,
(__int64)&off_4E2880,
(__int64)&v31,
v4,
v5,
(__int64)&off_4E2880,
qword_572B10,
(__int64)&unk_4C8569,
2LL);
runtime_stringtoslicebyte(a1, a2, v6, v7, v8, v9);
*(_QWORD *)&v10 = &v24;
*((_QWORD *)&v10 + 1) = v11;
runtime_slicebytetostring(a1, a2, v11, 1, v12, v10);
encoding_base64__ptr_Encoding_DecodeString(a1, a2, 1LL, (__int64)&v31, v13, v14, qword_572B00, (__int64)&v31);
v26 = (const __m128i *)1;
MEMORY[0x19](a1);
runtime_convTstring(a1, a2, v20);
*(_QWORD *)&v30 = &unk_4A6D00;
*((_QWORD *)&v30 + 1) = 1LL;
fmt_Fprintln(a1, a2, (__int64)&off_4E28A0, (__int64)&unk_4A6D00, v21, v22, (__int64)&off_4E28A0, qword_572B18);
v16 = v26;
if ( *(__int128 **)(v27 + 8) == &v31
&& (runtime_memequal(
a1,
a2,
(__int64)v26,
*(_QWORD *)v27,
v17,
v18,
v26,
*(const __m128i **)v27,
(unsigned __int64)&v31,
1),
v19) )
{
*(_QWORD *)&v29 = &unk_4A6D00;
*((_QWORD *)&v29 + 1) = &off_4E1140;
result = fmt_Fprintln(a1, a2, (__int64)v16, (__int64)&off_4E28A0, v17, v18, (__int64)&off_4E28A0, qword_572B18);
}
else
{
*(_QWORD *)&v28 = &unk_4A6D00;
*((_QWORD *)&v28 + 1) = &off_4E1150;
result = fmt_Fprintln(a1, a2, (__int64)v16, (__int64)&off_4E28A0, v17, v18, (__int64)&off_4E28A0, qword_572B18);
}
return result;
}
能看到一些scanf函数printf还有base64加密函数之类的,但是有一个重要的判断。在这个判断处下断点进行动态调试。输入一串测试字符1234567890
运行至判断处
cmp [rax+8],rbx
是比较输入长度和0x2A的值说明输入长度要为42,输入42个字符串重新调试。跳转成功继续运行出现,应该是比较进入这个函数
call runtime_memequal
里面有个比较
cmp rsi rdi
jz short loc_40240E
看下rsi和rdi地址里的值
rsi即为存放的flag,rdi为输入的字符。