buuctf [ACTF新生赛2020]rome

前言:学习笔记

深入刨析,打好基础~

 

常规:下载 解压 查壳

f1c36b7224904f5084390a7155841fe5.png

32位>>> 32IDA Pro 打开。

 

常规:先查找字符串 再进入main()函数

0ffcf9ef533d4f1288f143469d747f64.png

main():

ed2b0ddd208d4a59bce854f2c9a9e1cd.png

进入func:(我们复制func代码在sublime进行分析<<<<因为func看着比较复杂。)

程序分析:

第一部分:(注意点就是v7~v10的字节数)

61f6abae12024cba9d29de1826e97e44.png

第二部分:(考察对指针:p 取地址:& 取值:* 的理解)

3c2607245fd84de2b199e7b06a52d44d.png

第三部分:(验证)

ea650917eaef460d8572cfc6ad1c39e4.png

程序流程:

①        输入字符串,必须是ACTF{} +flag 的格式

②        遍历数组,判断 flag[i] 是否属于大写小写字母   if T >>> 执行对应的加密算法

【不属于。则不进行任何操作。】

③        遍历数组。判断加密后的flag[i] 是否等于v12[i]         if F>>>return flag[i]【结束程序,表明错了】

④        打印 printf("You are correct!"); 说明>>>正常退出,flag正确。

 

C逆向脚本:

脚本思路:

从后往前推。【逆向reverse嘛。】

 

原程序中第二个while只用于验证,所以不重要。

重点是对第一个while的逆推。

 

FF>>>(正向的while循环 写成C代码的样式如下:v1[i]是我们要求的flag。通过加密算法变成了v12.)

15cabe6e8fa248a2a445fae17b9cd080.png

因为加密后的结果为v12(已知)。

进行逆推(以大写为例)。

①        v12[i] 先减去 65 变成 (v12[i] -51)%26

 

②        因为”    (  ) 【运算优先级】   “,所以先逆括号里面的>>> (v12[i] + 51)%26

我用X代替(v12[i] + 51)

 

③        这时候需要小心。 X 的值分为两种情况:(该怎么解释->>>逆向%26 。。。T^T)

A        当 X  =>65(A)时          不用做任何矫正。【因为其范围就在大写字母之内】

B        当 X <65(A)时            则需要加上余数26   【为了确保其范围在大写字母之内】

问题一:为什么能够确保在大写字母之内?:

 

【原因:首先v12[i]属于大写字母,先 减65 ‘A’ 再 加51      结果会> 90 'Z' ??只能是( 结果① =>65  ||  结果②<65 )】

 

问题二:为什么要确保在大写字母之内?:请看 FF的内容。

 

题外话:取余 以及 取模。

69e76c1ecc1948a58596b8ae23e3a03e.png

 

脚本:

536f2e1552184cc58eaf9b7d86844abb.png

验证:

cd017d0be1f14ecf942d6c9e77a8ceeb.png

4574eb13e1c745e3966b5870fb3c13bc.png

flag{Cae3ar_th4_Gre@t}。

 

 

总结:

最大的难点在于对 %26的理解与处理、其次对 p & *的理解运用、以及char int 所占字节数等。 

 

%处理:

◎①若指定范围,例如本题矫正依据情况而定.

②若未指定,直接抄原代码.例如<buu-pyc>.◎

 

>>>若逆向结果在指定范围,则不需要进行矫正。

>>>若逆向结果在指定范围之外,则需要加上【%X】的【X】进行矫正。

if (v12[i] > 64 && v12[i] <= 90)//大写字母的范围
		{
			v12[i] = v12[i] - 65 + 51;//运算的值可能在范围内,也可能不在范围内。
			if (v12[i]< 65)			//对不在范围内的值进行矫正。
			{
				v12[i] += 26;
			{

拓展:^处理。

假设:(具体依据情况而定)

原	: for (int i = 0; i < strlen(FLAG) - 1; i++)
	{
		FLAG[i] ^= FLAG[i + 1];	//该位与后一位进行异或。 最后一位不异或
	}

则逆: for (int i = strlen(FLAG) - 1; 1 <= i; i--)
	{
		flag[strlen(FLAG) - 1] ^= FLAG[i]; //最后一位不异或,从后往前,异或还原。
	}

目前学习掌握的两种运算逆向。(继续学习)

23c00581aba345d4acdc19f990429c84.jpeg

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值