[NPUCTF2020]芜湖
!(https://tianyu.xin/usr/uploads/2022/03/937921903.png)挺明显的混淆痕迹
!(https://tianyu.xin/usr/uploads/2022/03/1149623066.png)
进来的函数长这样, 稍稍命名发现最好还是动调, 上面这一部分都没见输入, 不管啥都能动调拿不香么
!(https://tianyu.xin/usr/uploads/2022/03/1513960211.png)
它说了一大堆也没见输入.
!(https://tianyu.xin/usr/uploads/2022/03/99063848.png)
我盲猜好吧, 一共34条话, 每条长度在lenTable里, 信息在binTable里, binTable被解密之后输出, 但是我猜binTable没用完,后面还有
!(https://tianyu.xin/usr/uploads/2022/03/1118155824.png)
我尝试一下直接patch这个34, 让它再来一次(其实应该真的去看看这个bin有没有那么大, 但是我懒了)
好吧, 说到这儿我发现还得patch lentable, 我们还是去bintable看看猜测对不对
程序能访问到的最后一个是bin],0x5b0, 看看bin多长, 1472 = 0x5c0, 不过后面全是0, 看来猜错了.
可是应该也没有反调, 那答案究竟在哪里呢
!(https://tianyu.xin/usr/uploads/2022/03/2118936297.png)
lentable长度基本上都是32, 40之类的, 但是bin却用42做一行, 会藏在每行后面么? 把bintable按每行42个看..后面也都是空的, 没什么问题, 没有办法, 我们去func1里面看看吧
每次把v2的第i位取出, 做func1的第一个参数, 第二个参数则是'a'的第i位, 返回值填到v2的第i位
!(https://tianyu.xin/usr/uploads/2022/03/1054520769.png)
func1长这样
!(https://tianyu.xin/usr/uploads/2022/03/1060561046.png)
那我看来它就是构造了一个完全没用到的string, 然后返回了两个参数的一个逻辑运算值, 先分析下func1这个逻辑运算到底啥样的, v2 = !(a1 & a2) , v3 = !(a1& v2) ...
v4 = v2, v5 = !(v2 & a2), v6 = !(v5&v3), 化简一下 : !(!(!((a1a2)a2))(!((a1a2)a1)) ... 这东西应该就是.. a1^a2 ? 随便验证一下, 这就是五个与非门的串
```python
>>> def f1(a, b) :
... return not (a&b)
...
>>> def f2(a, b) :
... v2 = f1(a, b)
... v3 = f1(a, v2)
... v4 = v2
... v5 = f1(b, v4)
... return f1(v3, v5)
...
>>> f2(0, 0)
False
>>> f2(0, 1)
True
>>> f2(1, 1)
False
```
'a' 是0b110001, 这个输出汉字的变换明白了, 可是那个没用的string数据还是没有解开.
我觉得不妨尝试一下把那些数据也用同样的方式跑一下, 毕竟这程序也没别的地方了
!(https://tianyu.xin/usr/uploads/2022/03/1154751815.png)
这里我忽略了这个func2... 是在找数据的时候通过xref一层一层发现的, 那现在就有两个入手点了, 另外还看到了一个base64表, 我想从表这儿入手
!(https://tianyu.xin/usr/uploads/2022/03/1487677735.png)
看一下func2到底干了啥吧
!(https://tianyu.xin/usr/uploads/2022/03/2431882882.png)
都在围绕这个string1做事, 我们直接去string1的地址
!(https://tianyu.xin/usr/uploads/2022/03/2670539256.png)
是个Base64.. 我都看了一遍就是这些汉字串的Base64
(https://blog.csdn.net/xnightmare/article/details/103774379)
答案在这儿:
!(https://tianyu.xin/usr/uploads/2022/03/247320795.png)
晕, 这不是谜语题么, 这正常谁能想到啊, 不过转B64明文再解密这一步确实有点怪, 算提示?
写个脚本撕了吧, 每个=能提供两位的隐写
```cpp
#include <cstdio>
#include <cstring>
#include <cstdint>
#include <string>
using std :: string;
uint8_t binTable1 = {
{84u,84u,24u,89u,84u,56u,12u,47u,87u,56u,4u,47u,84u,0u,50u,47u,84u,84u,16u,36u,87u,0u,46u,46u,84u,17u,12u,23u,45u,38u,92u,92u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u},
... 略{2u,82u,55u,22u,59u,57u,40u,6u,3u,54u,39u,15u,0u,54u,44u,6u,5u,83u,88u,24u,3u,38u,51u,74u,7u,6u,92u,92u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u}
};
int lenTable1 = {
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 20, 40, 40, 40, 16, 32, 32, 32, 40, 24, 32, 24, 28, 20, 40, 28, 32, 28, 20, 40, 28, 32, 28, 0
};
string s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8_t b64;
void change(uint8_t* Src, uint8_t* Dst, int len) {
for(int i = 0; i < len; i ++ ) {
uint8_t tmp = 0;
for(int j = 0; j < 8; j ++ ) {
tmp = (tmp << 1) | (((Src >> (7 - j)) & 1) ^ (('a' >> (7 - j)) & 1));
}
Dst = tmp;
}
}
int main() {
for(int i = 0; i < 35; i ++ ) {
change(binTable1, b64, lenTable1);
}
for(int i = 0; i < 35; i += 2) {
uint8_t tmp = 0;
tmp = s.find(b64-3]) & 0xF;
tmp <<= 4;
tmp |= s.find(b64-3]) & 0xF;
putchar((char)tmp);
}
}
//npuctf{Fly1ng!!!}
``` 又是隐写 不明觉厉 这个帖子写的详细,看来是楼主自己操作的,我觉得有些地方可以模仿一些楼主。
页:
[1]