ConMiko 发表于 2022-4-13 11:53

bugku bingo逆向 全网最详细的讲解

​https://img-blog.csdnimg.cn/3dafd7900f994b5f83f0a67b4dc7b380.png

本题目有点烧脑子 但是我敢说这是全网唯一一个讲的最详细的教程,建议保存反复观看

下载得到的是一张图片,逆向题也哟图片估计要么就是可以解压要么就是里面放着个exe啥的
010看看
https://img-blog.csdnimg.cn/f44d7ca12216424497ebfed70c297e33.png
​按照图中的剪头可以发现
此时已经到达了PNG的底部,之后的任何代码都不属于PNG文件的范畴之内
看到了MZ就想到了EXE文件,所以将MZ开头到最后的所有hex提取出来即可
但是直接打开 打开不了

https://img-blog.csdnimg.cn/5dff949831c84ccd808f70a529405156.png​


仔细一看我PE头哪去了?
随便打开一个正常exe文件看看

https://img-blog.csdnimg.cn/eef8f199b520486bb40d08a65cc1c87a.png

https://img-blog.csdnimg.cn/2b76cb9875d240ce9fc95114ac920c5c.png

给他加个PE就行


https://img-blog.csdnimg.cn/64cf8a4900dc4047ae7d0761b0705617.png

写个PE就可以了 直接运行就能运行了,但是一会就闪退,拖到OD显示有壳子

用PEID看看是什么壳子


https://img-blog.csdnimg.cn/8ca791155ef44c81896de548d57f5fbe.png

PEID查壳是UPolyX 0.5.*这是一个单纯的压缩壳子

之前babyxor那道题也是这个壳子


https://img-blog.csdnimg.cn/908c7728ca33414fb0eade6b6332a552.png


https://img-blog.csdnimg.cn/636f8647034d4bcf8be0ac8b71933cdd.png

两者就是同一个壳子但是这个壳子是坏的 xor那条指令是执行不了的并且少了循环的代码


https://img-blog.csdnimg.cn/09f6ec6da408498185c5f81b28a2f025.png

就是单纯卡死在这所以我们就不加循环代码了,直接外部写个脚本xor解压一下就行了
首先UPolyX这个壳子会压缩.text段内的代码,并且从指令上可以知道是代码端与0x22进行异或,这个就简单了
用010打开比较直观一点,找到.text段 所有hex复制出去


https://img-blog.csdnimg.cn/3407970cd8a140f089d360c416bcd981.png

把所有hex复制到文档里空格替换为 ,0x ,\n\r替换为,0x 然后加个中括号大概就是这样的


https://img-blog.csdnimg.cn/9fc8b2870ac64635ac64ade3a6a04389.png

以下简写

a=
b=open("2.txt",'w')
for i in a:
    b.write(hex(i^0x22))
    b.write(" ")

a就是那个列表 具体太多了就不展开了最后得到这解码过后的hex
这边是需要你把.text段的hex给他xor一下 xor的脚本已经放在上面了,解码过后就行下面这些,把他们替换010之前看到的.text段的hex就行!请注意空格!!


https://img-blog.csdnimg.cn/6f5f541a35e44a378e7d1e013a15e048.png

把他复制替换到之前的.text代码段里保存即可再次拖到od直接把xorNOP掉 因为我们已经做了解压了 直接走到jmp大跳转到OEP即可


https://img-blog.csdnimg.cn/9f7e766b1f154384943948dd04f25f09.png


https://img-blog.csdnimg.cn/dd424a80376c4a5d9795da1b1facfada.png

直接到达OEP接下来脱壳,使用PE工具完整转存ImpREC IAT修复一下即可 这个壳子很快的 大致怎么修复可以看我上一篇文章脱壳完成后打开看看


https://img-blog.csdnimg.cn/7f52e056904646c894b7a3a49f6f03f0.png

拖到IDA看看


https://img-blog.csdnimg.cn/68582cfe1da3463c847bb4d3c01ec48f.png

主要就是判断v0得到的值是否与off_443DC0相等


https://img-blog.csdnimg.cn/e03d83554ef946e2ae0afb6f86b00eab.png

off_443DC0就是这串密文v0 = sub_401005(&v2, 52);传过去了输入的字符串和52
之后就是算法问题,胆小误入!

追一下这个函数sub_401005(&v2, 52)


https://img-blog.csdnimg.cn/53400a7c00924bb181da9a30dab7b44e.png

再追进去就是本题算法部分


https://img-blog.csdnimg.cn/9c62ffcb71924e38846f707112f8de75.png

这边过程是这样的
传参进来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
通过上面正序的代码可以得到逆序代码是

#include <stdio.h>
#include <string.h>
#include <cmath>
int main() {
    int v2; // ST6C_4
    signed int v3; // ST5C_4
    signed int i; //
    char v6[] = "zaciWjV!Xm
    char a1[] = "                        ";
    int a2 = 29;
    for ( i = 0; i <24; ++i )
    {
      v2 = pow(a2, 2.0);
      v3 = pow(v6, 2.0) + v2;
      ++a2;
      a1 = (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值
cd "c:\Users\xinra\Desktop\" && g++ 1.cpp -o 1 && "c:\Users\xinra\Desktop\"1
flag{woc_6p_tql_moshifu}
exited with code=0 in 0.325 seconds

C艹看不懂的我这边还写了一个python脚本来帮助理解

Python去改写IDA反编译出来的伪代码应该好理解点

import math
key="flag{woc_6p_tql_moshifu}"
flag=""
num=52
for i in range(24):
    fl = chr(int(math.sqrt(pow(ord(key),2.0)-pow(num,2.0))+0.5))
    num-=1
    flag+=fl
    flag=flag[::-1]
print(flag)

其实就是这样的这样子就得到了我们IDA里得到的密文,这么一看就很好理解了我们写倒序的版本也很好写

import math
key="zaciWjV!Xm[_XSqeThmegndq"
flag=""
num=29
for i in range(24):
    fl = chr(int(math.sqrt(pow(ord(key),2.0)+pow(num,2.0))+0.5))
    num+=1
    flag+=fl
    key=key[::-1]
flag=flag[::-1]
print(flag)

无非就是改索引 然后key反转最后跑出来也是一样得到flag

python -u "c:\Users\xinra\Desktop\t.py"
flag{woc_6p_tql_moshifu}

exited with code=0 in 0.136 seconds

最后也得感谢杭电暗黑芦苇大佬给算法逆向的思路


moshuiNW 发表于 2022-4-14 14:31

感谢,我比着做一做去

白云点缀的蓝 发表于 2022-4-14 15:50

学会了~很详细~

tukuai88ya 发表于 2022-4-14 16:23

学会了~很详细~

moshuiNW 发表于 2022-4-14 16:29

本帖最后由 moshuiNW 于 2022-4-14 16:48 编辑

我从这个大跳没有跳到oep 为什么??

ConMiko 发表于 2022-4-15 18:08

moshuiNW 发表于 2022-4-14 16:29
我从这个大跳没有跳到oep 为什么??

你解压没解压好吧

moshuiNW 发表于 2022-4-15 21:23

ConMiko 发表于 2022-4-15 18:08
你解压没解压好吧
我用你说的把所有hex提取出来然后保存为exe文件,也用了zsteg -E 直接把exe给提取出来
这两种方法都不行 真不知道要怎么解决了

ConMiko 发表于 2022-4-15 22:46

moshuiNW 发表于 2022-4-15 21:23
我用你说的把所有hex提取出来然后保存为exe文件,也用了zsteg -E 直接把exe给提取出来
这两种方法都不行 ...

.text段的hex啊 你肯定是哪里没弄好 你把你解码后的hex发一下我看看

ConMiko 发表于 2022-4-15 22:50

本帖最后由 ConMiko 于 2022-4-15 22:52 编辑

moshuiNW 发表于 2022-4-15 21:23
我用你说的把所有hex提取出来然后保存为exe文件,也用了zsteg -E 直接把exe给提取出来
这两种方法都不行 ...
我去 你提取出来要写脚本来xor解码 然后再把解码后的内容放到原处 就是原本的.text段内 然后保存之后OD调到OEP就能看见正常的了...你这完全理解错我的意思了啊 建议xor后对比我发上去的那段hex看看对不对 那些东西是要替换原本.text段的内容的 这种才是手动解压啊

1cy 发表于 2022-7-25 00:50

感谢分享
页: [1]
查看完整版本: bugku bingo逆向 全网最详细的讲解