前几天的XCTF最后一场终于打完了,三场比赛下来对逆向部分的大概感觉是从第一场的啥都不会做到后来的终于能有参与度了TvT,至少后两场的题目都是pc逆向,虽然特殊架构但好歹能做(tcl
本文是三场XCTF所有逆向题目的wp+复现整理。赛中拿到了7/10的flag,很多是跟着队里的大佬做出来的(tqltql),这边就试着独立复现一下,至少打完应该长长记性(
官方wp出了,借助wp提供的思路复现填坑√。(9/10)
1220那场的apk逆向还没复现完,因为博客要更新点配置所以就先放上来了qvq。
比赛官网:XCTF高校网络安全专题挑战赛
官方wp:
- XCTF高校网络安全专题挑战赛-华为云专场 官方Writeup - XCTF社区
- XCTF高校网络安全专题挑战赛-鲲鹏计算专场 官方Writeup - XCTF社区
- XCTF高校网络安全专题挑战赛-HarmonyOS和HMS专场 官方Writeup - XCTF社区
[12.20] 华为云专场
Weird_lua
根据官方wp,说是改了loadbyte和opcode顺序。这里假装没看过wp,看能不能分析出怎么看出来是这里魔改的。
首先看附件是lua
和check_license_out.lua
,可以用file分别看一下
单独运行./lua
,可以看到版本号是5.3.3
这里运行目标文件的方式是./lua ./check_license_out.lua
感觉这个.lua文件实际可能是.luac文件,即lua字节码文件。
于是先随便写一个lua源码(除了不知名check以外,大致对目标文件check_license_out.lua
进行复刻),用v5.3.3的lua(可以在lua官网Lua: download下载)编译成字节码,看看正常版和魔改版两个文件的区别。
1 | -- test.lua |
用lua test.lua
运行:(注意这里是用正常的lua解释器而不是题目给的)
然后用luac -o test.luac test.lua
得到test.luac
字节码文件,然后把check_license_out.lua
(上)和test.luac
(下)用010Editor打开对比十六进制码。
可以看到,除了最开始的一字节为”1B”和”1C”以外,其余文件头中不同的字节都相差较大,感觉是某个特定的换算关系,位置看起来却没什么规律。
定位到lua-5.3.3/src
文件夹中,有两个执行luac dump相关操作的头文件,分别是ldump.h
(save precompiled Lua chunks)和lundump.h
(load precompiled Lua chunks),这里猜测是用于load的lundump.c
被魔改。
从这里(类似于主函数的函数)开始是整个的load步骤,可以看到上面对比中第一个差距比较大的字节是在0004h的位置,应该是在checkHeader部分,跟进这个checkHeader()
函数。
237行是check文件头的"\x1bLua"
部分(题目开头0x1c这个很容易看出就是硬改),而下面开始是check LUAC_VERSION即lua的版本号,本来应该是0x53,但是题目文件对应位置是0xAC,而且往后对照可以看到,不同字节部分都用了LoadByte()
函数,猜测是在加载字节的时候有魔改,至于具体怎么魔改那可能得靠直觉了吧(。),大概能靠猜?(或者看lua
文件的反编译= =
在官方wp里,魔改的具体信息已经给了:
1 | static lu_byte LoadByte (LoadState *S) { |
跟着官方wp走不通的思路
本部分可跳过,最后因为刚刚接触lua,对这个语言不熟悉,卡在创造不出帖子里提到的 “用于 dump 的函数,尽量覆盖所有的指令操作,否则只能提取出已有的指令” 的lua函数,帖子里的test无法在5.3版本的lua中提取出所有字节码,需要自己动手创造(。
因为这里LoadByte的魔改会影响到下一步的opcode顺序还原,所以要先把这些错误字节xor回去。
又因为LoadByte的更改只影响到部分字节,我们并不清楚具体哪些字节遭到了祸害,所以想到了一个比较笨的方法就是重新编译一个lua解释器,这样我们就有了opcode顺序魔改前的解释器和魔改后的解释器(题目所给的)。
(如果有师傅有更好的办法求告知><)
将之前的lua-5.3.3
文件夹复制到一个新路径,cd到文件夹中,执行make clean
将文件中上一次的编译临时文件清空。其实理论上说不复制出来也应该不会影响到原来的lua,但为了保险起见还是这么干吧。
然后把lua-5.3.3/src/ldump.c
(注意文件名!!)的52-56行即DumpByte()
函数部分改为:
1 | static void DumpByte (int y, DumpState *D) { |
保存,退回到lua-5.3.3
根目录下,在WSL中用make linux
编译。
至于为什么是改ldump.c
而不是改官方wp指定魔改的lundump.c
,因为ldump.c
的作用是保存字节码,而lundump.c
的作用是加载字节码。这里参照[原创]用 Lua 简单还原 OpCode 顺序文中的方法进行还原。
帖子里的lua版本为v5.1.5,对这里v5.3.3并不能直接用(opcode有增加+有些5.3中新增的指令),需要对源码(Check_OpCode/check_opcode.lua
)做一些修改,修改后的文件如下。
1 | -- check_opcode.lua |
将题目附件的lua
重命名为lua_problem
并复制到Check_OpCode
文件夹中,同时将刚刚xor了字节的lua-5.3.3/src/lua
也复制过来。
P.S. 由于帖子中给出的test.lua
与前文中最开始用到的lua文件重名,故以下test.lua
均代表为帖子中的lua文件,前文中的test.lua
不再被引用。
依次在WSL中运行:
1 | ./lua dump_test_luac.lua |
(然后发现写不出能覆盖所有字节码的test()
,遂放弃该思路。
自创思路
我们知道在lua源码里,opcode是按顺序存放在lopcodes.h
和lopcodes.c
里的,故顺序魔改其实可以追踪lua解释器在ida中的反编译即可。(这里的lua
就是题目给的那个。
源码中的opcode处:
将lua
加载进ida中,用shift+F12
提取字符串,并用ctrl+F
搜索“MOVE”
双击,按x
找到交叉引用
这里就是魔改后的opcode顺序!
那么我们现在就掌握了所有魔改的信息,开始恢复还原。
这里用到的是著名的lua反汇编/反编译项目viruscamp/luadec: Lua Decompiler for lua 5.1 , 5.2 and 5.3,由于lua解释器被魔改(xor 0xff和opcode顺序),所以我们需要在原安装步骤的基础上做些调整。
1 | git clone https://github.com/viruscamp/luadec |
调整源码如下:
1 | /* luadec/lua-5.3/src/lopcodes.h 原line165-232 */ |
1 | /* luadec/lua-5.3/src/lopcodes.c 原line20-69 */ |
1 | /* luadec/lua-5.3/src/lundump.c 原line60-64 */ |
1 | /* luadec/lua-5.3/src/Makefile 原line9 */ |
1 | /* luadec/luadec/Makefile 原line16 */ |
修改完源码后接着make。
走完流程后把check_license_out.lua
的第一个字节改为"\x1b"
,以对上LUA_SIGNATURE,并复制到luadec/luadec
文件夹中。
然后在luadec/luadec
下运行:
1 | ./luadec -dis check_license_out.lua > discheck |
(如wp所说,反编译会报错,只能反汇编,估计是乱魔改的原因哈哈哈哈。
得到反汇编的discheck。
1 | ; Disassembled using luadec 2.2 rev: 895d923 for Lua 5.3 from https://github.com/viruscamp/luadec |
说是反汇编其实还是有一点反编译注释的吼。
根据注释来走就很容易理顺逻辑啦(可以参考深入理解 Lua 虚拟机_腾讯技术工程 - MdEditor),算法用python还原是:
1 | # Function 0_0: to_v() |
就可以根据逻辑写出exp:
1 | tb0=[172, 25, 60, 95, 5, 27, 49, 58, 171, 5, 253, 45, 87, 246, 197, 12, 97, 234, 159, 119, 157, 169, 121, 54, 242] |
得到flag
flag{th15_15_v3r7_c0mm3n}
divination[TO DO]
先用模拟器跑一下,发现是一个输入字符串判断的逻辑。
因为物理机里装了WSL2,所以用的是能兼容Hyper-V的BlueStacks模拟器。
走流程,先用pxb1988/dex2jar: Tools to work with android .dex and java .class files这个工具把将apk解压后文件夹中的classes.dex文件转换成jar文件,再用Java Decompiler中的JD-GUI查看反编译出的java源代码。
然后可以看到MainActivity.class这里也有一句“大事不妙”,找到主函数。
看了一下逻辑就是调用libdivination.so(在apk解压后的路径divination/lib/arm64-v8a/libdivination.so
),只要返回值为真就行。
所以其实做安卓逆向看so硬逆也能逆出来hhh。
于是现在转去逆so。
关键入口函数显而易见,就是这个跟包同名的函数。
为了方便看反编译代码,按y
把a1-a3三个参数的变量类型进行更改(ida无法自动识别。
下边的函数也一目了然。
从后往前看,先拿到目标数组unk_3000:
[12.23] 鲲鹏计算专场
mips
真·送分题,可惜当时要上课没来得及抢一血(下午2点放题绝了
老传统走迷宫
mips架构。
ida反编译以后可以看到
v4是我们输入的字符串,很明显是迷宫逻辑,上下左右用wasd走,迷宫存在dword_100111F0里。
sub_10000744()这个初始函数是用来找起点用的(就是迷宫中3所在的地方,在后面可以看到3其实表示的是当前位置)。
这里也可以看到应该有多个迷宫(dword_10011D10是用来表示第几个迷宫的,且<=2,一个迷宫有225个数)+一个迷宫宽为15=三个迷宫,每个迷宫为15*15。
然后就是下面的四个函数,随便挑一个出来(比如sub_10000D28())可以看到
很明显是个往右走的函数,3表示当前位置,并把上一个当前位置标为1(可走路径)。并且可以看到终点是4,就是说我们要把每个迷宫从3走到4。
dump迷宫数组,写脚本打印迷宫:
1 | aMap=[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 3, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0] |
可以看到打印出了三个迷宫,为了看得清楚所以选用几个特定字符打印。
1 | .....********** |
走迷宫,然后把路径拼起来,根据提示转md5,get flag。
(有个疑惑哈,第二个迷宫理论上说就算是最短路也有多解?是题目出锅了还是我哪里看漏了= =
(再补一句,题目似乎甚至没要求最短路???神奇.jpg
1 | import hashlib |
flag{999ea6aa6c365ab43eec2a0f0e5968d5}
pypy
把题目文件拖进ida,搜索字符串能看到
猜测是pyinstaller打包的文件。
也就是这个题让我突然发现pyinstaller还能打包成elf的,于是比赛结束以后赶紧把之前总结的解包指南更新了:RE套路 - 关于pyinstaller打包文件的复原 | c10udlnk_Log。
走流程解包,得到python源码。
看到这种混淆变量名,果断替换成ida style变量名(。
放一下源码:
1 | # uncompyle6 version 3.7.4 |
可以看到最后getflag这里(func())的程序逻辑就一个rc4加密,由rc4的特性可知加密和解密流程相同,故复用程序中的rc4()来得到flag。
uncompyle反编译出来的源码是python3,但是题目本身的源码是python2,注意编码问题。
关于编码问题,可以看:
这里因为反编译做了转换成python3的处理,所以脚本用python3写。
1 | DEFAULT_KEY = u'Y\xf3\x02\xc3%\x9a\x820\x0b\xbb%\x7f~;\xd2\xdc' |
flag{snake_bao_is_really_lucky}
官方wp说的是给了一个brainfuck引擎,跟我赛中攻击格式化字符串漏洞的思路完全不一样(。),一开始还以为我想得太偏了XD,然而在复现的时候发现这个brainfuck解释器的原理就是攻击格式化字符串漏洞,学到了学到了。
以下试图从头开始复现。
通过在DuckDuckGo上搜索setup()
中的特殊字符串"%1$.*1$d %2$hn"
查到一个github项目HexHive/printbf: Brainfuck interpreter inside printf,发现其余的字符串与题目中的十分相似,并且pbf_pre.c
跟程序逻辑几乎一样,推测是题目的来源。
所以先通过动态调试,把断点设在前面所有的赋值语句之后,用idapython的get_bytes(0x5577FCB50000,16000)
提取出progn的内容。
通过printbf项目中的pbf_pre.c
源码可以知道progn是int *,故将提取出来的byte对象进行处理,然后按照token.py
的逻辑逆向写出由progn反向生成的brainfuck程序。
1 | # token.py from "HexHive/printbf: Brainfuck interpreter inside printf" |
可以看到实际上就是从progn[2*k]这里看到brainfuck的每一步操作符,而对于”+-><”这四种操作符的数量由progn[2*k+1]给出,故从这些位置即可提取出bf程序的操作符,得到bf程序:
1 | p=b'' # 这里是动态调试提取出的progn字节对象,太长了这里不贴 |
得到:
1 | >,>,>,>,>,>,<<<<<[->>>>>>+<<<<<<<+>]<[->+<]>[->>>>>>+<<<<<<<+>]<[->+<]>>[->>>>>>+<<<<<<<<+>>]<<[->>+<<]>>[->>>>>>+<<<<<<<<+>>]<<[->>+<<]>>>[->>>>>>+<<<<<<<<<+>>>]<<<[->>>+<<<]>>>[->>>>>>+<<<<<<<<<+>>>]<<<[->>>+<<<]>>>>[->>>>>>+<<<<<<<<<<+>>>>]<<<<[->>>>+<<<<]>>>>[->>>>>>+<<<<<<<<<<+>>>>]<<<<[->>>>+<<<<]>>>>>[->>>>>>+<<<<<<<<<<<+>>>>>]<<<<<[->>>>>+<<<<<]>>>>>[->>>>>>+<<<<<<<<<<<+>>>>>]<<<<<[->>>>>+<<<<<]>>>>>>[->>>>>>+<<<<<<<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<]>>>>>>[->>>>>>+<<<<<<<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<]>>>>>>>[->>>>>>+<<<<<<<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]>[->>>>>>>>>>>>+<<<<<<<<<<<<<+>]<[->+<]>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>[->>>>>>>>>>>>+<<<<<<<<<<<<<<+>>]<<[->>+<<]>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<+>>>>>>>>>]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>[->>>>>>>>>>>>+<<<<<<<<<<<<<<<+>>>]<<<[->>>+<<<]>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<+>>>>>>>>>>]<<<<<<<<<<[->>>>>>>>>>+<<<<<<<<<<]>>>>[->>>>>>>>>>>>+<<<<<<<<<<<<<<<<+>>>>]<<<<[->>>>+<<<<]>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<+>>>>>>>>>>>]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>[->>>>>>>>>>>>+<<<<<<<<<<<<<<<<<+>>>>>]<<<<<[->>>>>+<<<<<]>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<<<<<<<]>>>>>>[->>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<]>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<+>]<[->+<]>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>]<<<<<<<<<<<<<<[->>>>>>>>>>>>>>+<<<<<<<<<<<<<<]>>[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<+>>]<<[->>+<<]>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<+>>>]<<<[->>>+<<<]>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<+>>>>]<<<<[->>>>+<<<<]>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<]>>>>>[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<+>>>>>]<<<<<[->>>>>+<<<<<]>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]>>>>>>[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<]>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<]>[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<+>]<[->+<]>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<]>>[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<+>>]<<[->>+<<]>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<]>>>[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>]<<<[->>>+<<<]>>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<]>>>>[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>]<<<<[->>>>+<<<<]>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<]>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>]<<<<<[->>>>>+<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<]>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>]<<[->>+<<]>>>>>>>>>[->>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>>>>>>>>[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>[->>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[->>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>[->>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>]<<<<<<<<<<[->>>>>>>>>>+<<<<<<<<<<]>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>]<<<<<[->>>>>+<<<<<]>>>>>>>>>>>>>[->>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>]<<<[->>>+<<<]>>>>>>>>>>>>>>>>>>>>>>[->>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>]<<[->>+<<]>>>>>>>>>>>>>>>>>>>>>[->>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>[->>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<]>>>>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>>>>>>>>[->>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>[->>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<]>>>>>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]>>>>>>>>>>>>>>>>>>>>[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<]>>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>]<<<[->>>+<<<]>>>>>>>>>>>>>>>>>[->>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]---------------------------->[-]+++++>[-]-------------------------------------------------------------------------------------------------->[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<<<<<<<<<<[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]++++++++++++++++++++++++++++++++++++++++++++++++<<<<<<[>>>>>>+<<<<<<[-]]>[>>>>>+<<<<<[-]]>[>>>>+<<<<[-]]>[>>>+<<<[-]]>[>>+<<[-]]>[>+<[-]]>>,>,>,>,>,>,>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]++++++++++++++++++++++++++++++++++++++++++++++++>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++<<<<<<<<<<<[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[->>>>>>-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[<<<<<<<+>>>>>>>[-]]>[<<<<<<<<+>>>>>>>>[-]]>[<<<<<<<<<+>>>>>>>>>[-]]>[<<<<<<<<<<+>>>>>>>>>>[-]]>[<<<<<<<<<<<+>>>>>>>>>>>[-]]>[<<<<<<<<<<<<+>>>>>>>>>>>>[-]]<<<<<<<<<<<<. |
进一步的,为了方便甚至可以直接转化成c程序,最后的处理脚本为:
1 | p=b'' #依旧是太长不贴( |
得到C程序:
1 |
|
于是现在的任务就成了分两次输入6个字符,经过处理后若mem[43]==48(原二进制文件中的判断逻辑)就能得到flag。
这个C程序还是比较冗杂(毕竟九百多行),所以对其进行找规律分析化简。
先拿出前四个while即[line 10, line 27]进行分析:
1 | while(mem[1]){ |
也就是说整段等同于:
1 | mem[7]+=mem[1]*2; |
所以接下来的(6-1)*4个循环也做相同处理,即[line 10, line 117]可以简化为:
1 | mem[7]+=mem[1]*2; |
然后再拿出四个while即[line 118, line 135]进行分析:
1 | while(mem[7]){ |
所以整段等同于:
1 | mem[13]=mem[1]+mem[7]; |
所以[line 118, line 225]简化为:
1 | mem[13]=mem[1]+mem[7]; |
最后[line 10, line 803]可简化为:
1 | mem[7]+=mem[1]*2; |
后半段输入后,处理的简化程序为:
1 | mem[50]=101; |
至此分析完成。
而mem[43]一开始赋值就是48,也就是说两个for循环都不能进到if里。令s[12]为所求字符串,则可以得出方程组:
1 | s[1]+s[2]*2+s[3]*3+s[4]*4+s[5]*5==53;//mem[2]+mem[9]+mem[16]+mem[23]+mem[30]==53; |
因为涉及到char型数据解方程的问题,s[0]-s[5]不好直接出,爆破又太慢了,所以决定构造一个程序用angr破:
1 | // useAngr.c |
useAngr_exp:
1 | import time |
解得:
有不可见字符,不过可以通过-0x80得到可见字符(估计是前面判定+和-的地方有点出入,问题不大)。
最后整理得到字符串:
1 | key1=b'\xd23v\xe5\xd2\xd3' |
由于要连远程拿flag,所以复现的时候只有本地打通没有flag,打通撒花~
R3veRSe_C0d3
[12.27] HarmonyOS和HMS专场
难得有一场ak逆向了!(虽然有大佬带着
有三道题都是卡着四血交,实惨TAT
re123
用file命令可以看到是MS Windows HtmlHelp Data文件(即.chm),查看文件头也可以知道。
所以添加后缀名.chm。
关于chm文件有一个常用的反编译器ChmDecompiler,可以释放CHM里面的全部源文件(包括网页、文本、图片、CHM、ZIP、EXE等全部源文件),并且完美地恢复源文件的全部目录结构 (摘抄的简介。
所以用ChmDecompiler打开re.chm,解压缩,可以看到目录下出现一个包含四个文件的文件夹(其实源文件只有三个,.hhp是ChmDecompiler自动生成的)。
一个一个翻可以看到doc.htm里有一段奇怪的Item1。
大概可以看到是powershell的语法?(感觉像win后门,这么多no的参数
查了一下其实就是把后面那大段进行base64解码而已,用wsl解一下base64有
然后得到了一段.NET代码(白字)。
通过查微软文档可以知道,这里是把base64解码以后的字符进行Deflate解压的过程,所以用脚本把中间那段base64解码,并整理输出。
1 | import base64 |
很明显的逻辑了,把doc.chm(应该是原来的re.chm)中”xxxxxxxx”后面的部分提取出来,还是用base64解码得到文件。
把这后面的内容手动复制出来到cont.txt里,进行base64解码,最后存在theFile中。
1 | base64 -d cont.txt > theFile |
查看theFile可以猜测是exe(毕竟最开始给的就是有powershell指令的base64),把文件头补上,并改后缀名(即theFile.exe)。
用ida打开,通过FindCrypt插件可以看到AES,跟过去能看到AES加密时的S盒(其实这里前两个都是S盒,第三个是逆S盒),猜测用到了AES加密。
往上回溯找到主函数
显然,这里是AES加密过程,sub_180001100()是密钥拓展过程,sub_1800015B0()是AES加密。
关于逆向中各种常见密码的记录,指路:对称加密算法&&Hash算法 文档 | feng’s blog
看了一下感觉是原装无魔改的AES,密文密钥都给了,那就直接写脚本解密。
注意这里是以整数形式给出的,别忘了小端序。
1 | from Crypto.Cipher import AES |
flag{youcangues}
puzzle
mips架构。
加载进ida以后,通过字符串回溯找到主函数。
可以看到很明显的sub_401134()这个check,先往这里面看。
看到是一个疑似maze的逻辑(
不过sub_400FA8()点进去以后可以看到是swap的功能
所以应该不是maze,是一个以交换为主的逻辑。
至于dword_4A0010,可以看到是一个九个数的数组。
v4和v5的出处在switch逻辑上面一点
可以看到最后(v4,v5)其实表示了数组里0的位置,且数组实际可以看成是3*3。
即:
1 | 4 0 3 |
最后sub_400FFC()的检查逻辑:
实际上就是要让这个3*3等于
1 | 1 2 3 |
把0看成空位的话,很容易就想到3*3的华容道了。
(或者玩算法的小伙伴可能对八数码问题这个名字更熟悉?
有本事下次出数织啊!20*20我都给你火速解出来(来自数织爱好者的吐槽)
这里实际上是求最短能得到的路径(15步),懒得想了,直接去网上抓了个现成代码下来改了改。
八数码问题的代码见:八数码问题-A*(AStar)算法实现_Broken Geeker-CSDN博客
1 |
|
得到每一步的情况,进而根据switch写出路径。
1 | 第 0 步 |
路径为“884226886224488”。
接下来看主函数里check上面的部分,看到sub_409070()实际上是一个scanf,而dword_4A1B60是我们的输入,也就是最后的flag,中间对输入进行处理以后才得到“884226886224488”这个字符串。
在里面翻可以翻到一个sub_400B58(),猜测是base64换表编码。
于是尝试写脚本编码。
1 | import base64 |
试试能不能过check。
wsl运行:(要装qemu才能执行,毕竟特殊架构。
1 | cp $(which qemu-mips) . |
执行mips程序,输入脚本中解出的字符串,发现成功了,get flag。
flag{8xOi6R2k8xOk6R2i7xOm}
aRm
arm架构。
照例通过字符串回溯找到主函数。
v1是key,v9是输入的flag,对输入的限制就是长度为42且头尾是“flag{”和“}”。
动态调一下可以发现,sub_27770()这个函数实际上是把unk_723A0数组里的42个数据复制到v8里。
1 | ./qemu-arm -L ./ -g 12345 ./aRm |
(Debugger选Remote GDB debugger,把端口号填上就好,其余配置具体见RE套路 - 关于使用IDA 7.0前端进行的动态调试 | c10udlnk_Log中调试elf部分。
现在我们未知的数就剩v5和v6了,v5要看sub_1714C()的输出,v6这里相当于是42条42元一次方程组(输入未知的情况下)。
而sub_105B4()是输出42个结果,于是可以知道只要输出了output.txt里的42个数就是正确的flag了。
由于前面有一个sub_169AC(key),这边又是一个无参的sub_1714C()+1,于是猜测是srand(seed)和rand()。
为了证明猜测,多次运行程序输入同一个key和相同/不同的flag,发现每一次的v5是一样的,结合rand()的伪随机性,确定这就是随机函数。
由于key只有一字节(0~255),干脆直接爆破。把output.txt的数据读入,用sympy库解方程,只要第一个解x0等于ord('f')^v8[0]=102^0xA0=198
,就说明这个key有极大可能性是正确的key。
当然,在此之前,我们得先知道每一次的v5(即方程的系数)是多少。
于是hook函数,在v5生成之后复用程序原来就有的print函数及格式符,把每次生成的v5都打印出来。
还记得有个函数是可以输出八位十六进制数的吧,就是那个sub_105B4(),我们可以用这里面的printf,然后把调用这个函数的地方nop掉(目标要明确,现在是为了爆破key,没必要管程序的正常性hahah)。
本来是想自己堆个调用printf出来的,不知道为什么keypatch对
LDR R0, =a08x
解释不了,于是只好绕个小路了。
转到汇编窗口,记一下这里的loc,等会要跳过来的。
看回去原来二重循环里出v5那个地方
这几条语句的意思就是f5里面的那行v5 = (unsigned __int8)(sub_1714C() + 1);
,我们从再下一行开始改。
注意可以改的范围在蓝框这里,这是我们不需要的v6[j] += (unsigned __int8)v9[k] * v5;
,在这个范围里可以尽情修改,剩下的nop掉。
用keypatch直接输入汇编,patch后面的语句为
(其实就是改了一行B loc_105D4
,剩下的直接Fill with NOPs就好)
接下来去往loc_105D4,改造一下。
我们知道,现在R3寄存器里实际上存的是v5的值,我们调用printf直接输出R3的值就能达成目标。
在ARM汇编里,函数传参用R0、R1……所以我们这里给R1一个R3的值就好。
这里本来就是MOV R1, R3
不用改,所以直接把前面nop掉。
因为v5那里是取(unsigned __int8),所以把这里改一下,把”%08x”改成”%02x”,就是出来的v5。
别忘了后面还要跳回去,找到地址:
patch:
记得把调用sub_105B4()的地方也nop掉。
最后把patch的字节保存一下。
运行测试一下,有:
ok,hook成功,开始爆破。
用pexpect进行批量的自动化交互见:【wp】2020ChaMd5圣诞题 | c10udlnk_Log
多亏了周五做的那个题,才有了这个题的爆破脚本(Doge。
1 | import pexpect |
爆破得到:
可知key是82,而v9在xor以后的数组也爆出来了,简单xor得flag:
1 | arr=[0xA0, 0xE4, 0xBA, 0xFB, 0x10, 0xDD, 0xAC, 0x65, 0x8D, 0x0B, 0x57, 0x1A, 0xE4, 0x28, 0x96, 0xB3, 0x0C, 0x79, 0x4D, 0x80, 0x90, 0x99, 0x58, 0xFE, 0x50, 0xD3, 0xF9, 0x3C, 0x0F, 0xC1, 0xE3, 0xA6, 0x39, 0xC3, 0x28, 0x75, 0xF8, 0xC9, 0xC8, 0xCD, 0x78, 0x26] |
flag{94bb46eb-a0a2-4a4a-a3d5-2ba877deb448}
pe
arm架构,没环境调不动,只能硬看了XD。这题有好多奇怪的函数,而且通过伪代码跟的话就能看到函数套函数套函数……所以基本靠猜出来的(
继续通过字符串回溯找主函数。
根据参数猜测,sub_1400023C8()是strcmp()的作用,我们需要让v9=”KIMLXDWRZXTHXTHQTXTXHZWC”。
再往上走,sub_1400015B0这个函数调用了v9,于是跟进去看功能。
感觉是某种加密,以相邻的两字符为一组,对这两个字符做相同的操作,再做后续处理。
跟进sub_1400012B8()里看,可以看到大概是一个搜索的过程
如果不等于-1就说明在表中找到了这个元素,然后返回一个索引(?
再往下看好像就看不太懂了,然后就是玄学的猜猜猜= =
回去看string可以看到一个这个,猜测是密钥表之类的?
往上回溯也看不到什么线索,不过可以发现这25个数字刚好没有相同的。
现在总结一下这个古典加密算法的特点,大概是两个为一组处理+已定义的密钥表(即不是通过输入生成的)5*5+处理时用到索引。
很久很久以前想写某对cp的AU同人时想把ctf元素混进去,就看了很多简单又奇奇怪怪的编码/古典密码(现代密码太学术了XD),没想到现在有用武之地了(手动狗头。
安利一个编码/古典密码的集合:CTF中那些脑洞大开的编码和加密 - jack_Meng - 博客园
然后翻到了一个符合这个特点的密码,Playfair Cipher:
不同的是密码表是直接给出的,不过加密流程再对回ida里的反编译感觉挺像的,于是果断试试。
按照Playfair Cipher的加解密流程写出脚本:
1 | def getIndex(c): |
走一遍脚本解密可以得到:
YES MAYBE YOU CAN RUN AN ARM PE
No, I can’t :(
看起来能读的通,成功get flag。
flag{YESMAYBEYOUCANRUNANARMPE}
crash
用binwalk分析给的crash文件
可以看到0x1000处有一个 ELF, 32-bit LSB executable
,先把这个可执行文件用dd分离出来。
其中if=输入文件名(被分离的),of=输出文件名(分离出来的),skip=跳过的块(bs指定字节)数,count=块长度,最后得到file_0x1000
文件。
用ida打开如果出现这个warning,可以用 Reinose/Useful-IDAScripts 的方法解决。
老样子,通过shift+F12
寻找字符串,通过交叉引用找到主函数。
先通过一些参数和常用逻辑的猜测给系统函数命名,方便后续分析。
然后就剩sub_8048737()
和sub_80487E7
这两个加密函数了。
第一个就很简单啦,简单xor。
第二个点进sub_80489E9()
可以看到md5经典常数,说明这一系列大概是个md5加密(当然md5的实现还是要看看的。
退回去,看到0x804B060
这里,很像数组的始地址。
于是转到IDA View,按G
跳到这个地址,可以看到一堆可见字符,按A
转成字符串。
再对回去逻辑就很明显了,就是依次取四个字符进行md5加密,然后跟这八个字符串比。
于是exp就可以写啦,爆破md5:
1 | # python2 |
得到flag:
flag{ux1cy1x4iltkahbc9nu1nk00d9akpp7w}