中职网络安全2022省赛之逆向PE01程序静态分析

简介

一次关于省赛逆向的笔记,有什么不会不懂的都可以问我,qq:162099475

开始

将PE01程序拖入到ida工具中
中职网络安全2022省赛之逆向PE01程序静态分析_第1张图片

1.对靶机服务器场景桌面上的PE01.exe二进制文件进行荆条调试,将main函数的入口作为Flag提交;

现在我们进入到程序中,可以发现左上角的主函数名中第一个为main函数。

中职网络安全2022省赛之逆向PE01程序静态分析_第2张图片

双击main函数,可以看见下面为main函数的入口地址
中职网络安全2022省赛之逆向PE01程序静态分析_第3张图片

Flag:0x0000000140001000

2.对靶机服务器场景桌面上的PE01.exe二进制文件进行静态调试,将该二进制文件中检查许可证的关键函数作为Flag值提交;

程序在进行判断的时候要么是正确的回显要么是错误的回显,类似c语言的if语句的判断。在PE01.exe程序中,输入字符出现了"wrong…"的错误信息
按空格键来到汇编代码窗口中
中职网络安全2022省赛之逆向PE01程序静态分析_第4张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第5张图片
按Alt加t键,搜索关键字符串
中职网络安全2022省赛之逆向PE01程序静态分析_第6张图片
中职网络安全2022省赛之逆向PE01程序静态分析_第7张图片

我们在这里点击wrong左上角的主函数,可以发现上面jnz指令跳转的为这个黄色主函数。call指令为回调地址,也就是说jnz跳转主函数后回调地址sub_1400016A0

中职网络安全2022省赛之逆向PE01程序静态分析_第8张图片

按F5键查看伪代码,由于ida并不是能完整的复现伪代码的所有真实数据,在这里可以发现if语句对sub_1400016A0函数进行判断。

中职网络安全2022省赛之逆向PE01程序静态分析_第9张图片

我们继续双击sub_1400016A0函数,来到了另一个伪代码中,在这里可以发现这是一些算法加上for循环语句进行if判断,这更加证明了sub_1400016A0函数就是检查许可证的关键函数

中职网络安全2022省赛之逆向PE01程序静态分析_第10张图片

点击汇编代码窗口,双击sub_1400016A0回调函数,可以看见它的入口地址为:00000001400016A0

中职网络安全2022省赛之逆向PE01程序静态分析_第11张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第12张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第13张图片

Flag:0x00000001400016A0

3.对靶机服务器场景桌面上的PE01.exe二进制文件进行静态调试,找到Flag值提交;

我们根据题目他提示继续分析Flag可能会出现的地方,双击main的函数,并在当前页面下按F5查看伪代码。

中职网络安全2022省赛之逆向PE01程序静态分析_第14张图片

在这里我们可以看见有两个函数地址,分别是sub_140001250和sub_140001920,双击sub_140001920函数,可以发现这里有些字符串的提示语句:“你好!也许秘密就藏在背景图片中”

中职网络安全2022省赛之逆向PE01程序静态分析_第15张图片

根据提示,联想到exe程序中默认是可以进行解压的,那么PE01.exe程序里的背景也是可以通过这种方式进行解压出来,我们将程序解压到PE01文件夹中,在.rsrc\2052\BITMAP的路径中发现了这张图片。

中职网络安全2022省赛之逆向PE01程序静态分析_第16张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第17张图片

将图片拖入到HxD工具中,在图片十六进制的末尾可以发现有一些可以可疑的十六进制值,将0去掉尝试猜解一些字符串,验证想法是正确的,编写一个脚本获取flag值

中职网络安全2022省赛之逆向PE01程序静态分析_第18张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第19张图片

在这里插入图片描述

脚本如下:

import re
str ='04 06 06 0C 06 01 06 07 03 01 07 0B 06 03 04 00 04 0E 07 04 05 0F 03 05 06 05 05 0F 06 0D 04 05 07 0D'

result = str.replace(' ','')
len_r = len(result)
flag = "" 
shiliu = ""

for j in range(1,len_r,2): 
    shiliu += (result[j])  
result1 = re.findall('.{2}',shiliu) 

for i in result1: 
    flag += (chr(int(i,16)))
print(flag) 

Flag:Flag1{c@Nt_5e_mE}

5.对靶机场景桌面上的PE01.exe二进制文件进行静态调试,将激活所需的许可证码作为Flag值提交;

我们在第2题得知sub_1400016A0函数就是检查许可证的关键函数,那么我们返回到这个函数的伪代码进行分析。

__int64 __fastcall sub_1400016A0(const WCHAR *a1)
{
  int i; // [rsp+20h] [rbp-28h]
  int v3; // [rsp+24h] [rbp-24h]
  _DWORD *v4; // [rsp+28h] [rbp-20h]

  v3 = lstrlenW(a1);
  v4 = malloc(saturated_mul(v3, 4ui64));
  for ( i = 0; i < v3 && i < 17; ++i )
  {
    v4[i] = (char)sub_1400017B0(LOBYTE(a1[i]));
    v4[i] = -v4[i];
    v4[i] ^= i + dword_140005044;
    if ( dword_140005000[i] != v4[i] )
      return 0i64;
  }
  return 1i64;
}

通过观察可以发现,许可证必须的等于v4[i]才能回显正确,那么我们求v4[i]的值等于求许可证的值,所以现在第一个目标是求v4[i],进行反编写脚本获取它的许可证码。

中职网络安全2022省赛之逆向PE01程序静态分析_第20张图片

可以发现求许可证的核心关键是for循环,那么我们只要关注for循环里的内容就好了,既然是逆向,逆向的脚本应该也是逆着来的,我们从后面开的函数分析。双击dword_140005000。

在这里可以发现这个变量里的数组有17个值。

中职网络安全2022省赛之逆向PE01程序静态分析_第21张图片

这个我们先不管,返回到伪代码窗口,继续向上分析,双击该变量名,跳转到该地址的数据段,在这里我们可以看见类似上面变量名的xxh这是汇编语言中的十六进制的表示符。

中职网络安全2022省赛之逆向PE01程序静态分析_第22张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第23张图片

现在我们知道这个变量名的数据段的值为那些十六进制,为了方便认识,按n键修改变量名字,将dword_140005044修改为key,v4修改为num。

中职网络安全2022省赛之逆向PE01程序静态分析_第24张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第25张图片

其中为了求出许可证我们知道num[i]必须恒等于dword_140005000[i],所以dword_140005000数据段里的17个十六进制值要等于num的变量名中的数组里的值。我们继续点击dword_140005000变量来到数据段里分析其中的十六进制值,为了方便认识,把它们都转为十进制。

中职网络安全2022省赛之逆向PE01程序静态分析_第26张图片

这里涉及到了十六进制转负数的知识点,如果直接进行进制转换可以发现有些数值是很大的,这不符合了十进制和ascii直之间的转换(0-127)。我们要判断十六进制是否为负数,只需要知道16进制首位是否大于8,大于8为负数,小于8为正数。

例如,在上图中dword_14000500变量里的数据段第一个十六进制值0FFFFFF9Ch,把它转为负数该如何进行操作?

  • 在汇编语言中为了避免将16进制数误认为是指令,需要在前面添加一个0

    • 所以0FFFFFF9Ch -> FFFFFF9Ch -> FFFFFF9C(前面讲解过h为十六进制标识符,这里不解释了)
  • 由于我们知道16进制首位大于8为负数,为了简单运算只留下一个F就够了

    • 所以 FFFFFF9C -> F9C
  • F9C 的二进制位为1111 1001 1100,这里由涉及了一个知识点十六进制转负数,简单来说就是求该二进制的补码就行。

  • 简单一个实验案例十六进制转负数

    • 1111 1001 1100 原码:为十六进制转为二进制的值
      0000 0110 0011 反码就是把原码的0和1改为相反数(原码求补码的过程要经历反码)
      1000 0110 0100 补码在最高位加1,证明它是负数,并且在最低为加1
      
      所以 F9C等于1000 0110 0100 (前面的1只是证明负数,运算的时候不理)
      -> 0110 0100 (转为十进制,注意添加符号,前面证明了是负数)-> -100
      

现在我们了解了那么多的信息,用python定义两个了变量

num =[-100,72,-98,-103,78,-118,61,-91,83,-74,-128,6,39,-93,117,-103,-65]

key = 65

继续分析上面的伪代码,其中-num[i]不理,后面编写逆向照着写就好了。在伪代码的左边可以发现chr函数,它的意义是转为ASCII值,num变量最后会经历ASCII的转码,这个时候ASCII输出的值也就是flag。我们双击sub_1400017B0,在这其中可以发现返回了一些算法的信息。其中a1是什么变量?根据伪代码a1[i]可以猜测出a1=num,其中0xFu中在十六进制不存在,所以编写脚本的时候应该改为0xF即可。

中职网络安全2022省赛之逆向PE01程序静态分析_第27张图片

中职网络安全2022省赛之逆向PE01程序静态分析_第28张图片

我们来到分析最后一行关键代码,可以看见是一个for循环,这有两种理解方式,一个是ida自动生成的伪代码并不标准,中间不可能出现与运算。二是因为我们知道num的数组有17位,那么for循环从零开始到16,遍历17次,所以这行代码应该理解为:

for ( i = 0; i < 17; ++i )

中职网络安全2022省赛之逆向PE01程序静态分析_第29张图片

最终用python脚本获取flag:

num =[-100,72,-98,-103,78,-118,61,-91,83,-74,-128,6,39,-93,117,-103,-65]
key = 65
flag = ""

for i in range (len(num)):
    num[i] ^= (i + key)
    num[i] = -num[i]
    num[i] = chr(16 * (num[i] & 15) | (num[i] >> 4) & 15)
    flag += num[i]
print(flag)

Flag:2o22_Ch1n@Ski1ls!

4.对靶机场景桌面上的PE01.exe二进制文件进行调试,尝试破解该二进制文件,将注册成功后的回显信息作为Flag值提交;

关于第四题篇幅和操作过长,可以参考我的另一篇教程:

https://blog.csdn.net/weixin_53912233/article/details/127282287

结尾

有什么不懂的话,可以评论区留言或者私信,我看到都会解答的

你可能感兴趣的:(中职网安比赛,逆向,安全,c#,github)