全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)

第一步首先想到的是,使用gdb打开,进行动态调试,但是我不知道怎样下断点在程序未运行时,下断点,因为它老是报错::

全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第1张图片

 

 

 

这些是对于文件的操作,找错方向了

搜索字符串read:

全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第2张图片

向上翻一点:

全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第3张图片

 

 

核心函数:

Go语言用IDA根本找不到调用的标准库函数,导致的结果是import窗口一片空白,所以确定核心函数很关键。

由Try again 的错误提示字符串,去winhex或者在IDA的hexdump(在hexview中直接搜索text,也能搜索到)中寻找,相应的字符串,它这个有点奇怪,再去找找正确(correct),竟然找到了:

复制左边的内存地址去,直接jump到指定地址,

               全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第4张图片

还找到了输入的提示信息:

         全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第5张图片

 

这是寻找成功的赋值代码的步骤,一步步寻找赋值的代码,点击右边黄色引用部分:


  1. 全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第6张图片

  2. 全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第7张图片

  3. 全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第8张图片

 

这是提示输入的字符Please input you flag like flag{123} to judge::

          全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第9张图片

这个是 Try again! Come on!  的赋值代码,找到字符串数据段的位置时,之后再找到调用的地方:

.text:0000000000495338                 lea     rax, off_4E1150    
        全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第10张图片

 

成功和失败都在一个子函数sub_495150下:

sub_4886B0 很可能就是打印函数(不知道为什么这里找不到打印函数),猜测

隔了一段时间,或者在不同的位置按下F5,之后类c代码会有些许的不同,但整体逻辑还是一样

开头4E1130,            成功:4E1140,         失败:4E1150,    

v37,v38,v39的赋值,都是这个4A6D00,可能是显示屏的设备号:

                          *(_QWORD *)&v37 = &unk_4A6D00;

__int64 __fastcall sub_495150(__int64 a1, __int64 a2)
{
  __int64 v2; // r8
  __int64 v3; // r9
  __int128 v4; // ST00_16
  __int128 v5; // ST10_16
  __int128 v6; // ST20_16
  __int64 v7; // r8
  __int64 v8; // r9
  __int64 v9; // rdx
  __int64 v10; // rcx
  __int64 v11; // r8
  __int64 v12; // r9
  __int64 v13; // ST18_8
  char v14; // dl
  __int128 v15; // ST00_16
  __int64 v16; // r8
  __int64 v17; // r9
  __int64 v18; // r8
  __int64 v19; // r9
  __int64 v20; // r8
  __int64 v21; // r9
  __int64 v22; // rdx
  __int64 v23; // rbx
  __int64 result; // rax
  __int64 v25; // rdx
  __int64 v26; // r8
  __int64 v27; // r9
  _QWORD *v28; // [rsp+8h] [rbp-F8h]
  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]
  __int64 v35; // [rsp+98h] [rbp-68h]
  _QWORD *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) )
    sub_44F5B0(a1, a2);
  sub_40B290(a1, a2);
  v36 = v28;
  *(_QWORD *)&v41 = &unk_4A6D00;
  *((_QWORD *)&v41 + 1) = &off_4E1130;
  sub_4886B0(a1, a2, (__int64)&v41, (__int64)&unk_4A6D00, v2, v3, (__int64)&off_4E28A0, qword_572B18);
  *(_QWORD *)&v40 = &unk_4A3E80;
  *((_QWORD *)&v40 + 1) = v36;
  *(_QWORD *)&v4 = &off_4E2880;
  *((_QWORD *)&v4 + 1) = qword_572B10;
  *(_QWORD *)&v5 = &unk_4C8569;
  *((_QWORD *)&v5 + 1) = 2LL;
  *(_QWORD *)&v6 = &v40;
  *((_QWORD *)&v6 + 1) = 1LL;
  sub_48EB00(a1, a2, (unsigned __int64)&off_4E2880, (__int64)&v40, v7, v8, v4, v5, v6, 1LL);
  sub_43F800(a1, a2, v9, v10, v11, v12);
  v14 = v13;
  *(_QWORD *)&v15 = &v33;
  *((_QWORD *)&v15 + 1) = v13;
  v29 = v31;
  sub_43F660(a1, a2, v14, v31, v16, v17, v15, v30);
  sub_47E620(a1, a2, v31, v30, v18, v19, qword_572B00, v30);
  v22 = v31;
  v23 = v30;
  if ( v32 )
  {
    v35 = v31;
    (*(void (__cdecl **)(__int64))(v32 + 24))(a1);
    sub_408B40(a1, a2, v25);
    *(_QWORD *)&v39 = &unk_4A6D00;
    *((_QWORD *)&v39 + 1) = v31;
    v29 = 1;
    sub_4886B0(a1, a2, (__int64)&off_4E28A0, (__int64)&unk_4A6D00, v26, v27, (__int64)&off_4E28A0, qword_572B18);
    v22 = v35;
    v23 = v30;
  }
  if ( v36[1] == v23 && (sub_4023F0(a1, a2, v22, *v36), v29) )
  {
    *(_QWORD *)&v38 = &unk_4A6D00;
    *((_QWORD *)&v38 + 1) = &off_4E1140;
    result = sub_4886B0(a1, a2, v22, (__int64)&off_4E28A0, v20, v21, (__int64)&off_4E28A0, qword_572B18);
  }
  else
  {
    *(_QWORD *)&v37 = &unk_4A6D00;
    *((_QWORD *)&v37 + 1) = &off_4E1150;
    result = sub_4886B0(a1, a2, v22, (__int64)&off_4E28A0, v20, v21, (__int64)&off_4E28A0, qword_572B18);
  }
  return result;
}

IDA远程linux动态调试:

需要配置的参数:

先找到虚拟机的ip地址:

          全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第11张图片

                              全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第12张图片

找到if语句分叉处,下断点:

动态运行,找到flag:

全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第13张图片

 

很奇怪的地方是,为什么,这个地方进行比较的是rax+8 和rbx,但比较的却是却是rdx的值:

全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第14张图片

 

64位程序,一边是16个F即64位

这个局部函数的一小段堆栈:

RSP:

 000000C000080E90  000000C000088580  debug002:000000C000088580

RBP:

000000C000080F88  000000C000080F90  debug002:000000C000080F90

 

 

左上角加载:

debug002:000000C00008A060 db  66h ; f
debug002:000000C00008A061 db  6Ch ; l
debug002:000000C00008A062 db  61h ; a
debug002:000000C00008A063 db  67h ; g
debug002:000000C00008A064 db  7Bh ; {
debug002:000000C00008A065 db  39h ; 9
debug002:000000C00008A066 db  32h ; 2
debug002:000000C00008A067 db  30h ; 0
debug002:000000C00008A068 db  39h ; 9
debug002:000000C00008A069 db  34h ; 4
debug002:000000C00008A06A db  64h ; d
debug002:000000C00008A06B db  61h ; a
debug002:000000C00008A06C db  66h ; f
debug002:000000C00008A06D db  2Dh ; -
debug002:000000C00008A06E db  33h ; 3
debug002:000000C00008A06F db  33h ; 3
debug002:000000C00008A070 db  63h ; c
debug002:000000C00008A071 db  39h ; 9
debug002:000000C00008A072 db  2Dh ; -
debug002:000000C00008A073 db  34h ; 4
debug002:000000C00008A074 db  33h ; 3
debug002:000000C00008A075 db  31h ; 1
debug002:000000C00008A076 db  65h ; e
debug002:000000C00008A077 db  2Dh ; -
debug002:000000C00008A078 db  61h ; a
debug002:000000C00008A079 db  38h ; 8
debug002:000000C00008A07A db  35h ; 5
debug002:000000C00008A07B db  61h ; a
debug002:000000C00008A07C db  2Dh ; -
debug002:000000C00008A07D db  38h ; 8
debug002:000000C00008A07E db  62h ; b
debug002:000000C00008A07F db  66h ; f
debug002:000000C00008A080 db  62h ; b
debug002:000000C00008A081 db  64h ; d
debug002:000000C00008A082 db  35h ; 5
debug002:000000C00008A083 db  64h ; d
debug002:000000C00008A084 db  66h ; f
debug002:000000C00008A085 db  39h ; 9
debug002:000000C00008A086 db  38h ; 8
debug002:000000C00008A087 db  61h ; a
debug002:000000C00008A088 db  64h ; d
debug002:000000C00008A089 db  7Dh ; }

或者Fllow in hex dump:

全国大学生信息安全竞赛(2019)--- easyGo(逆向,Go语言)_第15张图片

 

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

 

 

动态调试,思路错误,到最后的正确:

text:000000000043D880

11*16
0000000000429B6C  错误跳转

0000000000452B50  退出   sub_452B50


从上往下,越来越接近输出

sub_4886B0    
loc_42BB1C

loc_42BAC8
loc_42BB1C
short loc_42BA2B

sub_42B960
loc_42BB1C
loc_42BAC8
short loc_42BA2B
sub_409220
short loc_42FF2C

000000000042F322
000000000042E797

000000000042FF45		双call,第二个跳出函数
000000000042FACC

sub_435590
sub_42E8C0
sub_42E750

sub_42B960
sub_44F380
sub_4886B0

00000000004886B0
sub_42A7F0
000000000044F59A
sub_44F380
000000000042E83B

循环
.text:000000000042E750 mov     rcx, fs:0FFFFFFFFFFFFFFF8h
.text:000000000042E759 cmp     rsp, [rcx+10h]

000000000042E7D9
sub_44F380
 sub_42B960
sub_44F380
#########################################################3



0000000000452C12	//syscall                 ; LINUX - sys_read

0000000000452BE3     syscall                 ; LINUX - sys_write

.text:0000000000495338                 lea     rax, off_4E1150	这个是Try again的赋值代码

 

总结

没有思路前不要盲目的去做。要先了解程序的语言,再进一步分析。

 

你可能感兴趣的:(逆向工程)