go_go_go!

130次阅读
没有评论

go_go_go!

下载附件,似乎得到一个linux二进制可执行文件

直接丢进IDA

go_go_go!

找到main

go_go_go!

已经能看到 Go 的启动入口 rt0_amd64_linux → runtime_rt0_go。C 语言或汇编仅仅在做引导工作,真正的业务逻辑在 Go 运行时初始化之后。

go_go_go!

这才是真正的入口

// main.main
void __fastcall main_main()
{
  string *p_string; // rax
  int v1; // r8d
  int v2; // r9d
  int v3; // r10d
  int v4; // r11d
  char *ptr; // rbx
  int v6; // r8d
  int v7; // r9d
  int v8; // r10d
  int v9; // r11d
  __int64 v10; // rax
  int v11; // r8d
  int v12; // r9d
  int v13; // r10d
  int v14; // r11d
  __int64 i; // rcx
  unsigned __int64 j; // rcx
  __int64 v17; // [rsp-2Ch] [rbp-A8h]
  __int64 v18; // [rsp-24h] [rbp-A0h]
  __int64 v19; // [rsp-1Ch] [rbp-98h]
  __int64 v20; // [rsp+1h] [rbp-7Bh]
  _BYTE v21[11]; // [rsp+9h] [rbp-73h]
  __int64 v22; // [rsp+14h] [rbp-68h]
  char v23; // [rsp+1Ch] [rbp-60h] BYREF
  string *v24; // [rsp+3Ch] [rbp-40h]
  _QWORD v25[2]; // [rsp+44h] [rbp-38h] BYREF
  _QWORD v26[2]; // [rsp+54h] [rbp-28h] BYREF
  _QWORD v27[2]; // [rsp+64h] [rbp-18h] BYREF

  p_string = (string *)runtime_newobject(&RTYPE_string);  //初始化
  v24 = p_string;
  p_string->ptr = 0LL;
  v27[0] = &RTYPE__ptr_string;
  v27[1] = p_string;
  fmt_Fscan((unsigned int)off_4C2008, qword_5371C8, (unsigned int)v27, 1, 1, v1, v2, v3, v4);  //获取输入
  ptr = v24->ptr;
  v10 = runtime_stringtoslicebyte((unsigned int)&v23, v24->ptr, v24->len, 1, 1, v6, v7, v8, v9);  //逐字符切片
  for ( i = 0LL; (__int64)ptr > i; ++i )
    *(_BYTE *)(v10 + i) = (*(_BYTE *)(i + v10) + 2) ^ 0x23;    //每个字符ascii+2 并且与0x23抑或计算
  v20 = 0x114A5E776065687BLL;
  *(_DWORD *)v21 = 1108429378;
  *(_QWORD *)&v21[3] = 0x4245534042114A42LL;
  v22 = 0x5C445657165B4457LL;   //这里 v20, v21, v22 拼起来就是一个长度为 0x1B (27) 的固定字节序列 targetBytes
  for ( j = 0LL; (__int64)ptr > (__int64)j; ++j )
  {
    if ( j >= 0x1B )
      runtime_panicIndex(j, ptr, 27LL);
    v11 = (unsigned __int8)v21[j - 8];
    if ( (_BYTE)v11 != *(_BYTE *)(j + v10) )
    {
      v26[0] = &RTYPE_string;
      v26[1] = &off_4C1B68;
      fmt_Fprintln((unsigned int)off_4C2028, qword_5371D0, (unsigned int)v26, 1, 1, v11, v12, v13, v14, v17, v18, v19);
      return;
    }
  }
  v25[0] = &RTYPE_string;
  v25[1] = &off_4C1B78;
  fmt_Fprintln((unsigned int)off_4C2028, qword_5371D0, (unsigned int)v25, 1, 1, v11, v12, v13, v14, v17, v18, v19);
}

这里要对v21处理一下

go_go_go!

go_go_go!

payload

"""
根据 Go 程序 main.main 里的校验逻辑:
    (input[i] + 2) ^ 0x23 == target[i]
得出反推公式:
    input[i] = (target[i] ^ 0x23) - 2
"""

# v20 (8 bytes)
v20 = [0x11, 0x4A, 0x5E, 0x77, 0x60, 0x65, 0x68, 0x7B]

# v21 (11 bytes) —— 根据分析已经推复原为:
v21 = [0x42, 0x4A, 0x11, 0x42, 0x4A, 0x11, 0x42, 0x40, 0x53, 0x45, 0x42]

# v22 (8 bytes)
v22 = [0x5C, 0x44, 0x56, 0x57, 0x16, 0x5B, 0x44, 0x57]

target = v20 + v21 + v22
assert len(target) == 27

decoded_bytes = [ (b ^ 0x23) - 2 for b in target ]
decoded_str = ''.join(chr(x & 0xFF) for x in decoded_bytes)

print(f"[+] Target bytes : {target}")
print(f"[+] Decoded flag : {decoded_str}")

得到0g{RADIV_g0_g0_and_}esr3ver

变形一下

VIDAR{g0_g0_g0_and_rev3rse}

正文完
 0
评论(没有评论)