​
本题目有点烧脑子 但是我敢说这是全网唯一一个讲的最详细的教程,建议保存反复观看
下载得到的是一张图片,逆向题也哟图片估计要么就是可以解压要么就是里面放着个exe啥的
010看看
​按照图中的剪头可以发现
此时已经到达了PNG的底部,之后的任何代码都不属于PNG文件的范畴之内
看到了MZ就想到了EXE文件,所以将MZ开头到最后的所有hex提取出来即可
但是直接打开 打开不了
​
仔细一看我PE头哪去了?
随便打开一个正常exe文件看看
​
给他加个PE就行
​
写个PE就可以了 直接运行就能运行了,但是一会就闪退,拖到OD显示有壳子
用PEID看看是什么壳子
​
PEID查壳是UPolyX 0.5.*这是一个单纯的压缩壳子
之前babyxor那道题也是这个壳子
​
两者就是同一个壳子但是这个壳子是坏的 xor那条指令是执行不了的并且少了循环的代码
​
就是单纯卡死在这所以我们就不加循环代码了,直接外部写个脚本xor解压一下就行了
首先UPolyX这个壳子会压缩.text段内的代码,并且从指令上可以知道是代码端与0x22进行异或,这个就简单了
用010打开比较直观一点,找到.text段 所有hex复制出去
​
把所有hex复制到文档里空格替换为 ,0x ,\n\r替换为,0x 然后加个中括号大概就是这样的
​
以下简写
[Python] 纯文本查看 复制代码 a=[0xEE,....]
b=open("2.txt",'w')
[i]for[/i] i [i]in[/i] a:
b.write(hex(i^0x22))
b.write(" ")
a就是那个列表 具体太多了就不展开了最后得到这解码过后的hex
这边是需要你把.text段的hex给他xor一下 xor的脚本已经放在上面了,解码过后就行下面这些,把他们替换010之前看到的.text段的hex就行!请注意空格!!
​
把他复制替换到之前的.text代码段里保存即可再次拖到od直接把xorNOP掉 因为我们已经做了解压了 直接走到jmp大跳转到OEP即可
​
直接到达OEP接下来脱壳,使用PE工具完整转存ImpREC IAT修复一下即可 这个壳子很快的 大致怎么修复可以看我上一篇文章脱壳完成后打开看看
​
拖到IDA看看
​
主要就是判断v0得到的值是否与off_443DC0相等
​
off_443DC0就是这串密文v0 = sub_401005(&v2, 52);传过去了输入的字符串和52
之后就是算法问题,胆小误入!
追一下这个函数sub_401005(&v2, 52)
​
再追进去就是本题算法部分
​
这边过程是这样的
传参进来a1和a2,a1是你打进去的字符串,a2是固定值52
然后v7拿到a1的字符串长度,v6创建了一个新区域,memset设置v6值全为0
然后循环a1的字符串长度次数
v2是a2的2次方
v3是写入字符串 索引从小到大取字符 然后求得ascii码的二次方再去减去v2的值
然后v6的同一索引下字符设置成v3开方的结果加0.5 这边为什么加0.5是因为校准差值取整
然后a2递减不说了
strrev反转一次v6
这边怎么理解呢 这个反转作用很大
即循环0-23 次数1-24
该反转会让v6的索引值更改
如果字符是从0开始往上递增
反转为 0 10 201 3102…
正常为 0 01 012 0123
就是说每次索引从0 1 2 3往上加 之前的索引部分会进行反转
添加新字符时由于反转 添加字符索引-1的内容都反转一次
只要理解了这边的内容之后逆向算法就很简单了
由于循环次数为24次,a2在最后一次循环时-1没用上 所以a2最小为52-24+1
通过上面正序的代码可以得到逆序代码是
[C++] 纯文本查看 复制代码 #include <stdio.h>
#include <string.h>
#include <cmath>
int main() {
int v2; // ST6C_4
signed int v3; // ST5C_4
signed int i; // [esp+70h] [ebp-14h]
char v6[] = "zaciWjV!Xm[_XSqeThmegndq"; // [esp+74h] [ebp-10h]
char a1[] = " ";
int a2 = 29;
[i]for[/i] ( i = 0; i <24; ++i )
{
v2 = pow(a2, 2.0);
v3 = pow(v6[i/2], 2.0) + v2;
++a2;
a1[i] = (sqrt(v3) + 0.5);
_strrev(v6);
}
_strrev(a1);
printf("%s",a1);
}
这边v3+2是因为先前正序-2 所以倒序要+2
i/2是因为取整得到的是00 1122 33因为每次v6都会反转一次 按照正常排序应该是
0246810..97531 这样的 因为之后我们也写了一个反转 所以直接i/2取整就可以正常跑
不然也可以判断奇偶数来取
然后因为正序是从打到小来取a2的值
所以倒序就直接倒着来就行
正序最后还进行了一次反转 ,也就是说之前得到的最终的v6值其实又反转了一次
所以我们这样解必须也把最后得到的a1进行反转一次
运行得到flag值
[Running] cd "c:\Users\xinra\Desktop\" && g++ 1.cpp -o 1 && "c:\Users\xinra\Desktop\"1
flag{woc_6p_tql_moshifu}
[Done] exited with code=0 in 0.325 seconds
C艹看不懂的我这边还写了一个python脚本来帮助理解
Python去改写IDA反编译出来的伪代码应该好理解点
[Python] 纯文本查看 复制代码 import math
key="flag{woc_6p_tql_moshifu}"
flag=""
num=52
for i in range(24):
fl = chr(int(math.sqrt(pow(ord(key[int(i)]),2.0)-pow(num,2.0))+0.5))
num-=1
flag+=fl
flag=flag[::-1]
print(flag)
其实就是这样的这样子就得到了我们IDA里得到的密文,这么一看就很好理解了我们写倒序的版本也很好写
[Python] 纯文本查看 复制代码 import math
key="zaciWjV!Xm[_XSqeThmegndq"
flag=""
num=29
for i in range(24):
fl = chr(int(math.sqrt(pow(ord(key[int(i/2)]),2.0)+pow(num,2.0))+0.5))
num+=1
flag+=fl
key=key[::-1]
flag=flag[::-1]
print(flag)
无非就是改索引 然后key反转最后跑出来也是一样得到flag
[Running] python -u "c:\Users\xinra\Desktop\t.py"
flag{woc_6p_tql_moshifu}
[Done] exited with code=0 in 0.136 seconds
最后也得感谢杭电暗黑芦苇大佬给算法逆向的思路
​
|