HITBCTF 部分WriteUp ## MIsc ## - IRC checkin - tpyx - pix - read file ## PWN ## - once - babypwn - d - gundam ## Web ## - upload - Python's revenge ## Reverse ## - hacku ## Crypto ## - base ## Mobile ## - multicheck - ivysimple ## Misc ## **IRC checkin** 签到题,加入IRC flag写在公告里就行了 HITBXCTF{W3lcome_To_HITBXCTF_2018_Online_Qualifications} **tpyx** 拿到图片第一反应是丢进Stegsolve发现打不开,用winhex打开通过观察发现是IDAT的length存在问题,对长度进行修复。然后使用binwalk分析 ![image001.png][1] 发现存在一个zlib,对其进行分离得到两个新文件 ![image003.png][2] 继续对29进行分析发现还存在一个zlib,继续分离 ![image005.jpg][3] 得到两个新文件 ![image007.jpg][4] 打开28D28D,发现里面存在一串十六进制,通过分析发现这是一个7z文件,用winhex构造7z文件 ![image009.jpg][5] 密码写在注释里面,解压得到flag HITB{0c88d56694c2fb3bcc416e122c1072eb} **pix** 下载后得到文件: aee487a2-49cd-4f1f-ada6-b2d398342d99.SteinsGate 执行file命令,发现是一个png图片 ![image011.jpg][6] 用pngcheck检查执行,没发现错误,binwalk一下也没任何发现,就直接用stegslove打开,选择数据导出: ![image013.jpg][7] 保存后用file命令查看一下,如下: ![image014.jpg][8] 通过以上关键字搜索到如下信息: ![image016.jpg][9] 将从图片中导出的文件重命名为1.kdbx,通过以下链接https://fileinfo.com/extension/kdbx 下载keepass,打开1.kdbx,发现需要输入密码,由hint可知密码为hint+6位数字 参考如下链接:[https://bbs.ichunqiu.com/thread-36593-1-1.html][10] 生成了相应的字典进行爆破,得到密码为hitb180408 > hashcat64.exe -a 0 -m 13400 c:\Users\wangzt\Desktop\pix.hash > c:\Users\wangzt\Desktop\superdic1.txt --force > > hashcat64.exe -a 0 -m 13400 c:\Users\wangzt\Desktop\pix.hash > c:\Users\wangzt\Desktop\superdic1.txt --force --show ![image018.jpg][11] ![image019.png][12] ![image021.jpg][13] **read file** echo $input | grep -o "[[:punct:]]*" 从表面上看是只显示标点符号,但当输入$$时,输出了pid: ![image023.jpg][14] 由此可以判断他实际过滤的是输入,即只能输入标点符号,利用通配符寻到了flag的位置: ![image025.jpg][15] 但不能用直接输入cat之类的,于是用相同方法找到/bin/cat位置,用$()执行里面的命令, 最后payload: > $(~/../../???/??? ~/../????????????/????.???) 在文件底部找到flag: ![image026.jpg][16] ## Pwn ## **once** 程序主体 ![image027.png][17] 程序实现了一个双链表,允许改变一次链表节点 ,选项4进入子选项允许申请一次非fastbin堆块,允许写入一次,释放一次。 - 漏洞: - 当输入选项不符合要求是会打印puts地址 - 一次输入一次 - 双链表解连时存在一次任意内存写,内容不可控。 - 漏洞利用 - 首先通过打印puts获得libc地址 - 通过一次内存任意写改global_max_fast, - 此时申请堆块大小都会被计算为fastbin,寻找fastbin时能够得到libcdata段地址,通过改写file vtabl getshell - 最终脚本 ![image029.png][18] ![image030.png][19] **Babypwn** - fmt盲pwn - 通过格式串dump bin文件 ![image031.png][20] - 修复ida解析得到printf got表 - 通过对比发现libc和once相同,格式串改写printf got getshell - 最终脚本 ![image033.png][21] ![image035.png][22] **d** - 程序主体 ![image036.png][23] - 实现功能 puts("1. read message"); puts("2. edit message"); puts("3. wipe message"); puts("4. exit"); - 漏洞 - 存在单字节溢出 - 利用 - 通过单字节溢出漏洞制造unlink拿到指向bss自身指针 - 通过指针更改got内容完成info leak 和getshell - 输入长度由strlen控制需要将strlen改为alarm_plt+6使输入长度变大 - 最终脚本 ![image038.png][24] **gundam** - 程序主体 ![image039.png][25] ![image041.png][26] - 结构体 struct { int inuse; char* name; char type[0x18] } - 程序在bss段保存列表和计数 - libc版本位2.26 - 漏洞 - 在选项3删除时bss列表中的指针没有清空,可以double free - 利用 - 通过多次删除堆块,满足tcahce的上限(7),将堆块放入arena的bin中得到libc中得地址,完成地址泄露 - 利用tcache实现任意地址写 - 最终脚本 ![image043.png][27] ![image045.png][28] ## Web ## **Upload** 经过扫描开放的web端口的指纹,得知服务器为windows,IIS7,php。这里考 察的是windows下<<符号可以,用于替代路径上的未知字符。 1.上传test.pHp ![image047.jpg][29] ![image048.png][30] 2.访问 > http://47.90.97.18:9999/pic.php?filename=default.jpg ![image049.png][31] 3.使用绕过gd库的脚本生成图片马,再次上传,一样有出现 width和height。 有上述步骤确认,可以上传为后缀为pHp,文件,目录与default.jpg 同级。 于是开始爆破default.jpg 所在目录。 ![image051.jpg][32] 得知 > wwwroot/87194f13726af7cee27ba2cfe97b60df/default.jpg 访问第一次上传的pHp ![image053.jpg][33] 使用kali自带的weevely生成php后门,可getshell **Python's revenge** 这里考察的就是pickle反序列化的问题,我们可以控制反序列化的内容,就可 以直接构造`__reduce__`魔术方法任意命令执行 但这里加了一个hook装饰器对callback进行过滤,然后用的是黑名单过滤,发 现可以用map函数去绕过黑名单的限制 整理一下大概思路就两步,关键主要是黑名单绕过吧: > 1. 访问`/reminder`生成location, 本地爆破secret,得到secret : hitb > 2. 利用map函数绕过黑名单任意命令执行, 构造恶意的location, 访问首页即可触发反序列化漏洞 ![image055.jpg][34] 没有回显的命令执行,直接用weblog方式带出来 ![image057.jpg][35] ## Reverse ## **Hacku** 解压缩包得到一个流量包和一个chm Chm里很显然包含着后门执行程序 通过hh.exe可以将其解包,在doc.htm中发现了后门程序的执行 ![image059.jpg][36] 通过powershell隐蔽执行了一段b64,解密后发现是一段Unicode ![image061.jpg][37] 又是一段b64,解b64后又用了DeflateStream解压缩 查了一下zlib什么的乱七八糟很麻烦,干脆直接去掉IEX即可 ![image063.jpg][38] 得到一段脚本 观察发现通过nslookup对x.hacku.org发起解析,返回的字符串解b64后执行 于是去流量包里找DNS ![image065.jpg][39] 将流量包dump出来并清洗后解析,得到下一段脚本 ![image067.jpg][40] 仅混淆了函数名,通读一遍后标记即可 逻辑为向cc.php发包,再解析返回的包来执行指定的命令 发包和收包都是先b64,再逐字符加密,再b64一次 于是分别写出发包和收包的解密函数,从流量包中dump出data,然后解密 ![image069.jpg][41] Recv中可以看到data有两种,指定传输moliboom文件和下载并执abs_stage3 Moliboom的发包中可以解出path和txt,在fix后的数据中找到flag的前半段 Abs_stage3返回的字符串被ps执行了,所以显然也是脚本 但是混淆很严重,包括大小写混杂、逆序、replace等 ![image071.jpg][42] 粗看一遍大概能发现是写入了某个exe并执行,然后删除 由于是exe,因此一定会落地在磁盘里,在ISE中调试即可捕捉到 ![image073.jpg][43] 在执行前断住,然后通过路径和文件名去找这个文件 抓住以后进行反编译 值得一提的是,sub_401050是个花指令控制函数,通过堆栈的操作使得ret跳到[eax]个字节之后的地址。需要手动/脚本将其后的 花指令nop掉才能使IDA正常反编译 程序开启了磁盘的交互 ![image075.jpg][44] 对主扇区的512和1024处进行了写入 ![image077.jpg][45] 这里是MBR(主引导程序)的地址,因此实际上是个勒索病毒吧233 分别将418DB0和4187b0dump下来 查了一下,MBR是直接送给CPU执行的汇编程序,因此同样按照x86反汇编 Dump下来以后用IDA打开即可查看 注意MBR是16bit模式 ![image079.jpg][46] 16bit模式无法使用F5,所以只能生啃汇编 好消息是MBR的空间有限,程序不会太过复杂 猜测应该是简单的加密以后直接对硬编码进行cmp 因此通过查找cmp可以在一定程度上加快速度 里面的读写调用都是通过int 10/13/16来执行的,具体方法跟ax参数有关 不进行动态调试的话难度有点大,因为没法准确锁定读写的函数 Sub_0x457是input函数,循环接受最多16个字符,值得一提的是没有退格,输入一个算一个。或者遇到0x0d,即回车也会提前结束 Sub_0x494是check函数,对input进来的内容进行一些变换,然后与硬编码cmp 主要逻辑在这里 ![image081.jpg][47] 做题的时候最好还是动态调试,因为猜逻辑太难了233 动态调试主要参考52论坛的@willJ的方法 https://www.52pojie.cn/thread-173889-1-1.html 在此附加一些个人经验,和对本题的特殊之处 首先要重新启动一个ida,在进入界面选择“GO” 直接附加会内存指令无法正常显示 因为MBR的入口点在0x7c00处,该dump程序会自动被装载到0x7c00起点的地方。 自己用汇编程序编译出来的MBR似乎会自动将入口点放在合适的0x7c00,使得动态调试直接命中。 但是dump下来的idb起点是0x00,也许前面放上一些00使其偏移过去也行? 按照文章附加上以后在0x7c00处下断,此时该处为空值,无视它继续下断,再F9即会断下 单步运行到check函数中 ![image083.jpg][48] 发现ax中放着输入的字符,先ror3,sub_4df是花指令,无视即可,再依次执行xor0x74, rol5,add0x47 最后按照最低位为0/1来-1/+1 之后与bx+141处的值cmp,全部dump下来后逆向求解即可 脚本: r = [37, 161, 57, 137, 166, 157, 213, 165, 117, 141, 74, 146, 241, 89, 94, 145] a = [i+1 if(i&1) else i-1 for i in r] for i in range(16): print(chr(rol(ror((a[i]-0x47)&0xff, 5)^0x74, 3)), end='') cmp成功以后会输出一个”}\n”来补齐 与之前流量包中的前半段flag合并后提交完成 Flag: HITBXCTF{W0rk_1n_th3_dark_ Tu_s4v@thr#1Ig&q} ## Crypto ## **Base** 这个一开始没思路,然后就开始爆破,最终爆破出flag。但是题目提示了不用爆破,显然我们使用了非预期算法。 ![TIM截图20180418214627.png][49] ## Mobile ## **Multicheck** 反编译发现load了"libcheck.so",但是没有导入native函数 反射了com.a.Check类中的check方法,这个类暂时没有发现 顺手瞟一眼claz.dex,逐字符比较了一个看起来像是flag但显然不是flag的字符串 出题师傅的恶趣味真是~ 于是Java层中暂时没什么线索了,反编译so看看 在init_array中发现了一个函数,跟过去往里看 ![image087.jpg][50] Sub_1380里有一些令人在意的东西 ![image089.jpg][51] 新建了一个文件,往里写了一些内容 把byte_4004里的值异或后dump下来 打开发现是个dex,反编译得到com.a.check类 ![image091.jpg][52] ![image093.jpg][53] Check方法里将arg和硬编码b进行了比较 然后一路跟着a进去,是4个同名不同参的重载函数 先整理了个数,将bytes后移,第一个byte存储偏移,之后补0 ![image095.jpg][54] 然后每8个byte一组,转成两个int(大端序) ![image097.jpg][55] 然后是核心变换,与之前强网杯的hide算法相同 32轮迭代,每轮先对key自增,然后互相运算 逆起来很简单,按着逻辑先把v1自增32次,然后将v2自减,再将v3自减,最后v1自减即可 然后有一个关键问题就是,之前的hide是elf格式的,而这次在安卓中的jvm中执行,写了python脚本怎么跑都不对 由于是不同的dex,jeb也跟不进反射的方法,Xp hook的话又太麻烦。 最后突发奇想复制到java环境里执行,果然得到了正确的逻辑: Java中>>为带符号的右移,要考虑各个参数的正负,如果是负数>>时应补1。 Python调了半天都没修正好,默认的int是无限宽度的,必须用0xffffffff去修正,而这会导致符号丢失。 调了一万年以后突然想起来何苦非要用python写脚本呢,遂将java的check类逻辑小改,得到flag ![image099.jpg][56] 解码脚本: ``` import java.util.Arrays; public class HelloWorld { public static void main(String[] args) { int i; byte[] t = { 99, 124, 101, -23, -114, 81, -47, -39, -102, 79, 22, 52, -39, -94, -66, -72, 101, -18, 73, -27, 53, -5, 46, -20, 97, 11, -56, 36, -19, -49, -112, -75 }; byte[] tt = re(t); for(i=0;i> 8 & 0xFF)); arrayOfByte[(paramInt + 1)] = ((byte)(paramArrayOfInt[i] >> 16 & 0xFF)); arrayOfByte[paramInt] = ((byte)(paramArrayOfInt[i] >> 24 & 0xFF)); i += 1; paramInt += 4; } return arrayOfByte; } private static int a(byte paramByte) { int i = paramByte; if (paramByte < 0) { i = paramByte + 256; } return i; } private static int[] b(byte[] paramArrayOfByte, int paramInt) { int[] arrayOfInt = new int[paramArrayOfByte.length >> 2]; int i = 0; while (paramInt < paramArrayOfByte.length) { arrayOfInt[i] = (a(paramArrayOfByte[(paramInt + 3)]) | a(paramArrayOfByte[(paramInt + 2)]) << 8 | a(paramArrayOfByte[(paramInt + 1)]) << 16 | paramArrayOfByte[paramInt] << 24); i += 1; paramInt += 4; } return arrayOfInt; } public static byte[] re(byte[] paramString) { return re_a(paramString); } public static byte[] re_a(byte[] arrayOfByte) { /*int i = 8 - paramArrayOfByte.length % 8; byte[] arrayOfByte = new byte[paramArrayOfByte.length + i]; arrayOfByte[0] = ((byte)i); System.arraycopy(paramArrayOfByte, 0, arrayOfByte, i, paramArrayOfByte.length);*/ int i; byte[] paramArrayOfByte = new byte[arrayOfByte.length]; i = 0; while (i < paramArrayOfByte.length) { System.arraycopy(re_c(arrayOfByte, i, a, 32), 0, paramArrayOfByte, i, 8); i += 8; } return paramArrayOfByte; } static byte[] re_c(byte[] paramArrayOfByte, int paramInt1, int[] paramArrayOfInt, int paramInt2) { int[] ArraryInt = b(paramArrayOfByte, paramInt1); int i = ArraryInt[0]; paramInt1 = ArraryInt[1]; //System.out.println(Integer.toHexString(i)); //System.out.println(Integer.toHexString(paramInt1)); int k = 0; int m = paramArrayOfInt[0]; int n = paramArrayOfInt[1]; int i1 = paramArrayOfInt[2]; int i2 = paramArrayOfInt[3]; int j = 0; while(j 0 ) { paramInt1 -= ((i << 4) + i1 ^ i + k ^ (i >> 5) + i2); i -= ((paramInt1 << 4) + m ^ paramInt1 + k ^ (paramInt1 >> 5) + n); /*System.out.print((paramInt1)); System.out.println("\t");*/ k += 1640531527; j -= 1; } ArraryInt[0] = i; ArraryInt[1] = paramInt1; return a(ArraryInt, 0); } } ``` **Kivysimple** 先查了一下,发现kivy是python开发apk的套件 那么很显然,这种套件的逻辑应该是在安卓中安装python虚拟机,然后将py编译成pyc/pyo来执行 扫了一圈assest和lib,没有发现pyo 不过lib中看到了python27.so,基本可以确定我们的判断 Libmain.so这个名字很吸引人,进去看一眼 查字符串,发现 ![image101.jpg][57] 都是python的原始代码,也就是说虚拟机确实在安卓中解释执行代码了 虽然还是没有发现程序的代码,但是注意到有很多自带的log,于是进行安装运行尝试 ![image103.jpg][58] 发现虚拟机在这个路径里,过去看看 ![image105.jpg][59] 一下就抓到了关键,将它pull出来并反编译 ![image107.jpg][60] 出题师傅的恶趣味真是~x2 显然关键在b64解出来的代码里,于是将eval去掉,查看code object的信息 PS:由于源代码为python2所写,因此必须使用python2来解码。Python3的marshal格式不同,会报错。 ![image109.jpg][61] 可以看到有一个check函数,也是code object 先通过dis模块来解析字节码 ![image111.jpg][62] 啥都没有╮(╯_╰)╭就是调用了check函数而已 于是再解析check ![image113.jpg][63] 还好没有很复杂的结构,基本上看单词和值就能大差不离的猜出来 ``` s = flag if(len(s)!=31): return False if(s[17]!=’7’): jmp 54 … ``` 下面都是类似的结构 因此只要把对应的下标和值提取出来即可得到flag 数据清洗使用正则匹配,或者手动复制都可233 得到flag: HITB{1!F3_1S_&H%r7_v$3_pY7#ON!} [1]: http://www.lovei.org/usr/uploads/2018/04/560512278.png [2]: http://www.lovei.org/usr/uploads/2018/04/70187211.png [3]: http://www.lovei.org/usr/uploads/2018/04/1714273776.jpg [4]: http://www.lovei.org/usr/uploads/2018/04/1777485047.jpg [5]: http://www.lovei.org/usr/uploads/2018/04/2806602389.jpg [6]: http://www.lovei.org/usr/uploads/2018/04/4124386620.jpg [7]: http://www.lovei.org/usr/uploads/2018/04/3760655958.jpg [8]: http://www.lovei.org/usr/uploads/2018/04/1828121343.jpg [9]: http://www.lovei.org/usr/uploads/2018/04/3570037921.jpg [10]: https://bbs.ichunqiu.com/thread-36593-1-1.html [11]: http://www.lovei.org/usr/uploads/2018/04/3578640221.jpg [12]: http://www.lovei.org/usr/uploads/2018/04/682792358.png [13]: http://www.lovei.org/usr/uploads/2018/04/1444394316.jpg [14]: http://www.lovei.org/usr/uploads/2018/04/4099964717.jpg [15]: http://www.lovei.org/usr/uploads/2018/04/2812539190.jpg [16]: http://www.lovei.org/usr/uploads/2018/04/3999711842.jpg [17]: http://www.lovei.org/usr/uploads/2018/04/10088187.png [18]: http://www.lovei.org/usr/uploads/2018/04/913622159.png [19]: http://www.lovei.org/usr/uploads/2018/04/3697922262.png [20]: http://www.lovei.org/usr/uploads/2018/04/3691018462.png [21]: http://www.lovei.org/usr/uploads/2018/04/981505821.png [22]: http://www.lovei.org/usr/uploads/2018/04/216111368.png [23]: http://www.lovei.org/usr/uploads/2018/04/503448941.png [24]: http://www.lovei.org/usr/uploads/2018/04/2822439988.png [25]: http://www.lovei.org/usr/uploads/2018/04/541132077.png [26]: http://www.lovei.org/usr/uploads/2018/04/263070655.png [27]: http://www.lovei.org/usr/uploads/2018/04/839821288.png [28]: http://www.lovei.org/usr/uploads/2018/04/2314311234.png [29]: http://www.lovei.org/usr/uploads/2018/04/3191307267.jpg [30]: http://www.lovei.org/usr/uploads/2018/04/4057632436.png [31]: http://www.lovei.org/usr/uploads/2018/04/3978456479.png [32]: http://www.lovei.org/usr/uploads/2018/04/456995951.jpg [33]: http://www.lovei.org/usr/uploads/2018/04/610016534.jpg [34]: http://www.lovei.org/usr/uploads/2018/04/4106065965.jpg [35]: http://www.lovei.org/usr/uploads/2018/04/3874977517.jpg [36]: http://www.lovei.org/usr/uploads/2018/04/1235275826.jpg [37]: http://www.lovei.org/usr/uploads/2018/04/3542478872.jpg [38]: http://www.lovei.org/usr/uploads/2018/04/3391078139.jpg [39]: http://www.lovei.org/usr/uploads/2018/04/1604219043.jpg [40]: http://www.lovei.org/usr/uploads/2018/04/3397770348.jpg [41]: http://www.lovei.org/usr/uploads/2018/04/1279316944.jpg [42]: http://www.lovei.org/usr/uploads/2018/04/2961097692.jpg [43]: http://www.lovei.org/usr/uploads/2018/04/2172923182.jpg [44]: http://www.lovei.org/usr/uploads/2018/04/973158994.jpg [45]: http://www.lovei.org/usr/uploads/2018/04/396506574.jpg [46]: http://www.lovei.org/usr/uploads/2018/04/1048182096.jpg [47]: http://www.lovei.org/usr/uploads/2018/04/1193452315.jpg [48]: http://www.lovei.org/usr/uploads/2018/04/3215810251.jpg [49]: http://www.lovei.org/usr/uploads/2018/04/1533841198.png [50]: http://www.lovei.org/usr/uploads/2018/04/3839152332.jpg [51]: http://www.lovei.org/usr/uploads/2018/04/300547490.jpg [52]: http://www.lovei.org/usr/uploads/2018/04/2093886879.jpg [53]: http://www.lovei.org/usr/uploads/2018/04/1714261865.jpg [54]: http://www.lovei.org/usr/uploads/2018/04/591665737.jpg [55]: http://www.lovei.org/usr/uploads/2018/04/1264023644.jpg [56]: http://www.lovei.org/usr/uploads/2018/04/453515523.jpg [57]: http://www.lovei.org/usr/uploads/2018/04/1417384868.jpg [58]: http://www.lovei.org/usr/uploads/2018/04/524482232.jpg [59]: http://www.lovei.org/usr/uploads/2018/04/3555119071.jpg [60]: http://www.lovei.org/usr/uploads/2018/04/3582254755.jpg [61]: http://www.lovei.org/usr/uploads/2018/04/3107809290.jpg [62]: http://www.lovei.org/usr/uploads/2018/04/1852392828.jpg [63]: http://www.lovei.org/usr/uploads/2018/04/3637140602.jpg