写一波wp来证明自己的菜。
这一道这么简单的题还花了我半天的时间,菜的扣脚。
先总结一波吧。
这道题总体的思路就是base58.然后还加入无关的数据来增加分析的难度,让人误会base64.
可能是自己的正向基础不太好,导致我静态分析了半天,然后动调,最后复刻出函数才明白关键算法。
0x01:
通过correct字符串找到关键函数F5查看伪代码。
找到了关键的对比信息,现在查找‘s’的来源:
向前回溯,找到输入点:
进入上面的sub_400D00
发现输入0x17个字符,存放在v4中,然后进入encode,给encode重命名进行分析
这个函数点恶心,加入了与结果无关来的算法来增加你的分析难度。
上面第一个for循环,看似从数组里取了有用的值,还取到了输入的值。最后分析到关键判断,根本没有用到。这里就是浪费分析时间的。
这里是我最困惑的,放在C语言的编译器里,n为1,但是我动调出来的结果是0x17。这里也卡了我好长时间。
这里的n是最为关键的。对比字符串的长度为22位,这里的len刚好就是0x17-1为22
接着就是最关键的算法了
这里有很多没用的代码来增加我们分析的难度。可能是我自己菜的原因,这个代码我静态分析了好久都没看明白是怎么回事。最后把这个函数复刻了一遍,才明白这个函数真正的道理是什么。
1 | //自己复刻了一遍base58的关键算法 |
这里就是将我们输入的第一位对58进行取模,大于58则进1,以此类推。第二位加上前面左移八位之后的数,然后再对58取模直到0。然后依次类推。
为了能算出flag
最后我们能逆向思考,当我们正确的输入flag,这个函数算到最后不就是,将每一个字符都左移八位,然后加上后面直到结束。最后存放在数组里面的值用一个式子表示:
flag[0]<<8*22+flag[1]<<8*21+ flag[2]<<8*20+flag[3]<<8*19+
flag[4]<<8*18+flag[5]<<8*17+ flag[6]<<8*16+flag[7]<<8*15+…
然后再将这个值转成58进制存放在数组里,然后根据数组里的值做索引去:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
取出值,然后和D9cS9N9iHjMLTdA8YSMRMp做比较。
然后思考写出exp:
可以根据比较的字符串,得到最后数组里面存放的值。
然后将数值里面的值转为十进制,这个时候是十进制就是flag[0]<<8*22+flag[1]<<8*21+ flag[2]<<8*20+flag[3]<<8*19+
flag[4]<<8*18+flag[5]<<8*17+ flag[6]<<8*16+flag[7]<<8*15+…
的结果。
我们发现这个式子8位刚好为一个字符。也就是说这个式子将我们的输入的值每个字符向左移位。为了得到flag,我们也只需将最后的式子和0x100取模。
最后exp如下:
1 | Exp: |