国赛2019逆向 easyGo lebel:golang / debug段的用处

go语言函数堆栈
在这里插入图片描述
运行程序,这题输入的格式为flag{xxxxx},两种方式:一种输入做加密与固定值比,一种固定值加密与输入比,这题是后者
遇到go语言先file一下,发现去符号了
ida golang helper后
先搜字符串,没有什么发现,说明关键字符串被加密了,看imports,也没有什么发现
分析main_main函数

大致流程

输入后对某变量base64,程序结尾的==和memcmp,而且每个分支都有print函数,猜测这里为关键点进行分析,整理伪代码如下

__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
  __int64 v10; // rdx
  int v11; // er8
  __int64 v12; // r8
  __int64 v13; // r9
  __int64 v14; // r8
  __int64 v15; // r9
  const __m128i *v16; // rdx
  unsigned __int64 v17; // rbx
  __int64 result; // rax
  __int64 v19; // rdx
  __int64 v20; // r8
  __int64 v21; // r9
  __int128 v22; // [rsp+0h] [rbp-100h]
  __int128 v23; // [rsp+0h] [rbp-100h]
  __int64 *v24; // [rsp+8h] [rbp-F8h]
  __int128 v25; // [rsp+10h] [rbp-F0h]
  __int64 v26; // [rsp+10h] [rbp-F0h]
  __int64 v27; // [rsp+18h] [rbp-E8h]
  char v28; // [rsp+18h] [rbp-E8h]
  char v29; // [rsp+18h] [rbp-E8h]
  __int64 v30; // [rsp+20h] [rbp-E0h]
  __int64 v31; // [rsp+28h] [rbp-D8h]
  __int64 v32; // [rsp+30h] [rbp-D0h]
  char v33; // [rsp+58h] [rbp-A8h]
  char v34; // [rsp+80h] [rbp-80h]
  const __m128i *v35; // [rsp+98h] [rbp-68h]
  __int64 *v36; // [rsp+A0h] [rbp-60h]
  __int128 v37; // [rsp+A8h] [rbp-58h]
  __int128 v38; // [rsp+B8h] [rbp-48h]
  __int128 v39; // [rsp+C8h] [rbp-38h]
  __int128 v40; // [rsp+D8h] [rbp-28h]
  __int128 v41; // [rsp+E8h] [rbp-18h]

  if ( (unsigned __int64)&v34 <= *(_QWORD *)(__readfsqword(0xFFFFFFF8) + 16) )
    runtime_morestack_noctxt(a1, a2);
  runtime_newobject(a1, a2);
  v36 = v24;
  *(_QWORD *)&v41 = &unk_4A6D00;
  *((_QWORD *)&v41 + 1) = &off_4E1130;
  fmt_Fprintln(a1, a2, (__int64)&v41, (__int64)&unk_4A6D00, v2, v3, (__int64)&off_4E28A0, qword_572B18);
  *(_QWORD *)&v40 = &unk_4A3E80;
  *((_QWORD *)&v40 + 1) = v36;
  *(_QWORD *)&v22 = &off_4E2880;
  *((_QWORD *)&v22 + 1) = qword_572B10;
  *(_QWORD *)&v25 = &unk_4C8569;
  *((_QWORD *)&v25 + 1) = 2LL;
  fmt_Fscanf(a1, a2, (unsigned __int64)&off_4E2880, (__int64)&v40, v4, v5, v22, v25, (unsigned __int64)&v40, 1LL, 1LL);
  runtime_stringtoslicebyte(a1, a2, v6, v7, v8, v9);
  v10 = v27;
  *(_QWORD *)&v23 = &v33;
  *((_QWORD *)&v23 + 1) = v27;
  v28 = v31;
  runtime_slicebytetostring(a1, a2, v10, v31, v11, v23);
  encoding_base64__ptr_Encoding_DecodeString(a1, a2, v31, v30, v12, v13, qword_572B00, v30, v31);
  v16 = (const __m128i *)v31;
  v17 = v30;
  if ( v32 )
  {
    v35 = (const __m128i *)v31;
    (*(void (__fastcall **)(__int64))(v32 + 24))(a1);
    runtime_convTstring(a1, a2, v19);
    *(_QWORD *)&v39 = &unk_4A6D00;
    *((_QWORD *)&v39 + 1) = v26;
    v28 = 1;
    fmt_Fprintln(a1, a2, (__int64)&off_4E28A0, (__int64)&unk_4A6D00, v20, v21, (__int64)&off_4E28A0, qword_572B18);
    v16 = v35;
    v17 = v30;
  }
  if ( v36[1] == v17
    && (runtime_memequal(a1, a2, (__int64)v16, *v36, v14, v15, v16, (const __m128i *)*v36, v17, v28), v29) )
  {
    *(_QWORD *)&v38 = &unk_4A6D00;
    *((_QWORD *)&v38 + 1) = &off_4E1140;
    result = fmt_Fprintln(a1, a2, (__int64)v16, (__int64)&off_4E28A0, v14, v15, (__int64)&off_4E28A0, qword_572B18);
  }
  else
  {
    *(_QWORD *)&v37 = &unk_4A6D00;
    *((_QWORD *)&v37 + 1) = &off_4E1150;
    result = fmt_Fprintln(a1, a2, (__int64)v16, (__int64)&off_4E28A0, v14, v15, (__int64)&off_4E28A0, qword_572B18);
  }
  return result;
}

静态分析

由储备知识盲猜 (__int64)&off_4E2880是输入存储的地址, (__int64)&v40是输入的长度,剩下的不太好分析,那么就动态分析

动态分析

输入123456789abcdefg 0x10个数
想找输入存的位置,但不好找,写了个脚本想在栈里找输入,失败了,在debug段里找输入,成功了,第一次用debug段,留个坑
调试发现debug,stack,vvar,vdso,vsyscall段在调试后出现的
在这里插入图片描述

#debug002段开始地址
begin = 0xC000000000
end = 0xC000200000
x = end-begin
for i in range(1,x-1):
    addr = begin+i
    if(Byte(addr-1) == 0x39 and Byte(addr) == 0x61 and Byte(addr+1) == 0x62 and Byte(addr+2) == 0x63 and Byte(addr+3) == 0x64 and Byte(addr+4) == 0x65 and Byte(addr+5) == 0x66):
        print(hex(addr))

注意到flag{92094daf-33c9-431e-a85a-8bfbd5df98ad}也是在debug段

flag{92094daf-33c9-431e-a85a-8bfbd5df98ad}

研究一下debug段

经过几次调试,debug段存储的应该是在动态调试中所有新出现的信息
比较有意思的几个点:

  • 在main刚开始时debug段里是没有flag{92094daf-33c9-431e-a85a-8bfbd5df98ad},在stringtoslicebyte后debug段里就出现了flag{92094daf-33c9-431e-a85a-8bfbd5df98ad},说明这个函数与flag有关
  • 在最后调用printf打印回显信息前,debug段没有Congratulation,调用后就有了

以后做题过程中,可以考虑一下debug段的信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

q1uTruth

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值