某市2023网安·论道逆向题-easyreee(8/30新增第二个解法思路)

文章描述了一种基于ASCII字符的加密过程,通过异或操作和无符号整数转换来隐藏和还原flag。解密的关键在于理解ASCII字符值加上75不会超过255,以及如何利用逆向工程从已知的加密结果反推出原始字符。
摘要由CSDN通过智能技术生成

入口
在这里插入图片描述
v4=dword_4020

dword_4020 = [
  26, 26, 200, 22, 198, 20, 58, 61, 197, 19, 194, 64, 189, 186, 188,
  116, 187, 118, 191, 75, 75, 75, 123, 180, 77, 98, 97, 173, 96, 86, 99,
  175, 120, 84, 86, 116
]

先校验input的s长度是否为36

再对字符串s每一位过加密函数sub_11c9
(需要注意这里返回值是无符号的int8)
在这里插入图片描述
在里面对当前s[i]+75然后和 无符号int的(i-75)进行 异或
最后返回对比v4
在这里插入图片描述
需要注意这里 方法返回值是无符号uint8转换后的 和v4对比

因为里面i-75得出来的是个负数 无符号转换之后得到的是个很长的整数
在这里插入图片描述
和前面异或之后长度足以被截断
在这里插入图片描述

====================
=(2023/8/29更新另一个解法,感谢h**er师傅提供的脚本和思路)

可以看到下面师傅的脚本中除了异或后转正码之外,并没有额外增加字符转换的部分

key = [26, 26, 200, 22, 198, 20, 58, 61, 197, 19, 194, 64, 189, 186, 188, 116, 187, 118, 191, 75, 75, 75, 123, 180, 77, 98, 97, 173, 96, 86, 99, 175, 120, 84, 86, 116]

flag = ""

for s in range(len(key)):
    flag += chr((key[s] ^ (s - 75) & 0xFF) - 75)

print(flag)

其根本原因为:因ascii中flag中可能会出现的有效字符的值+75无论如何都不会超过255:如下例100为ascii的’d’的值
在这里插入图片描述
以至于在二进制中数位是无论如何都不会操作到8位之后的9位,下例为100+75的175二进制,可见其为8位

在这里插入图片描述
我们先正着走一遍 ,这里我们直接可以拿未经uint处理的-75进行异或 (-75所对应的二进制为-0b1001011)
在这里插入图片描述
得到-230也就是-0b11100110 ,依照题意我们将其转化为无符号的数值,我这里先不用uint8截取8位,用unit直接获取全部的值
在这里插入图片描述
得到
在这里插入图片描述
其二进制为0b11111111111111111111111100011010
我们截取最后8位00011010转换为10进制即为26 对应着cipherlist的第一位在这里插入图片描述
当然这是在已知答案的情况下进行正向运算。

接下来我们反过来从逆向的角度利用一下这个条件
list第一位是26 依照我们直接将他与第一轮询的(i-75)也就是(0-75)= -75进行异或还原

(26 ^ -75)

得到-81对应的二进制-0b1010001

而后我们将其转换为无符号得到4294967215

在这里插入图片描述
其所对应二进制为0b11111111111111111111111110101111
我们取他的8位10101111即为175 ,然后175-75=100就是最初的’d’

为什么我们可以这样肆无忌惮的直接用不过任何处理cipher与轮询值做异或呢

说白了就还是因为他ascii可还原的值不会超过255,整个过程我们只需要关注到无符号步骤需要转换一次,取一下8位即可,也就是即便int8截取了8位之后也影响不到数据的完整性,255也就代表了8位全1,我们折腾一顿自始至终也是在8位内,丝毫不需要考虑到会被截取导致无法还原明文值,当然这一切都是建立在flag字符目标的值+75没有超过255的情况下。假如他符号给的值超过了255话,那就只能用下面的方式进行爆破了。

====================
他做了uint8截断之后会丢失原来的位数 比赛时候没想出什么好的办法还原。

于是打算撞出来,但是卡住了
这是我的脚本
#正数与负数的异或是统一为正数后进行异或然后再转负数

import ctypes
import string
dword_4020 = [
  26, 26, 200, 22, 198, 20, 58, 61, 197, 19, 194, 64, 189, 186, 188,
  116, 187, 118, 191, 75, 75, 75, 123, 180, 77, 98, 97, 173, 96, 86, 99,
  175, 120, 84, 86, 116
]
s=string.printable
flag = ""
for i in range(len(dword_4020)):
  for j in s:
    x = ctypes.c_int8((ord(j) + 75) ^ ctypes.c_uint32(i - 75).value).value
    if x == dword_4020[i]:
      flag+=j
print(flag)

但是挺怪的输出的是 dacc66b5ee876e5acf9eb76a

赛后用c重新写了一遍 才发现我掉了个u…这里输出的结果被认定为有符号8位截断了…
在这里插入图片描述
举个例子
在这里插入图片描述

最后脚本为
在这里插入图片描述

import ctypes
import string
s=string.printable
dword_4020 = [
  26, 26, 200, 22, 198, 20, 58, 61, 197, 19, 194, 64, 189, 186, 188,
  116, 187, 118, 191, 75, 75, 75, 123, 180, 77, 98, 97, 173, 96, 86, 99,
  175, 120, 84, 86, 116
]
for i in range(len(dword_4020)):
  for j in s:
    x=ctypes.c_uint8((ord(j)+75) ^ ctypes.c_uint32(i-75).value).value
    if x == dword_4020[i]:
      print(j,end="")

很简单的re题,可惜了
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值