HCTF已经过去很久了,整理一下其中两个简单逆向题的Writeup。
0×01. NormalFile
题目给了一张图片,把图片后缀改为zip,然后打开,有两个关键的地方:一个是解压根目录下有一个隐藏的desktop.ini文件,文件内容为“加油。。flag就在你眼前!”,基本没用;另一个是_MACOSX下隐藏了另一张图片。同样将图片的后缀改为zip后打开,基本断定这是一个APK文件,使用十六进制编辑器打开PNG图片文件,搜索IEND标志找到PNG文件末尾,删除PK标志前面所有的数据,就得到APK文件了。
解压APK文件,使用dex2jar可以将classes.dex转为jar文件,就可以使用jd-gui来看Java代码了,这个代码没有混淆。使用apktool对apk进行反编译,在res\values\strings.xml中发现一个奇怪的字符串。
<string name="half">401!n++p</string> |
使用jd-gui发现Main函数里面的一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | do { char[] arrayOfChar1; do { while (true) Toast.makeText(getApplicationContext(), "Oh... Why don't you try that? :(", 0).show(); arrayOfChar1 = paramString.toCharArray(); } while ((arrayOfChar1[15] != arrayOfChar1[13]) || (arrayOfChar1[4] != arrayOfChar1[9]) || (arrayOfChar1[5] != arrayOfChar1[8]) || (arrayOfChar1[7] != arrayOfChar1[10])); String str2 = "" + paramString.charAt(0) + paramString.charAt(4) + paramString.charAt(8) + paramString.charAt(12) + paramString.charAt(1) + "++" + paramString.charAt(13); int[] arrayOfInt = { 112, 83, 93, 112, 28, 0, 87, 91 }; arrayOfChar2 = new char[8]; for (int i = 0; i < 8; i++) arrayOfChar2[i] = (char)(str2.toCharArray()[i] ^ arrayOfInt[i]); } while (!("" + paramString.charAt(2) + paramString.charAt(6) + paramString.charAt(10) + paramString.charAt(14) + paramString.charAt(3) + '+' + paramString.charAt(11) + '+').equals(new String(arrayOfChar2))); Toast.makeText(getApplicationContext(), ":) I'm happy to see your favorite toast is just the same as me:hctf{" + paramString + '}', 0).show(); |
这段代码的对输入的字符串进行了校验,大概校验关系就是:
其中,ord(‘+’) xor 91 = ord(‘p’),第一行后面的三个字符为++p,刚好为half后面的三个字符,因此尝试将half字符串应用到第一行的下标,求出整个字符串4nDr01cl10l|!pQp,拼接为Flag即hctf{4nDr01cl10l|!pQp}。
0×02. wow
直接运行程序coredump,在gdb下面可以调试,果断上gdb,当然结合IDA静态分析效果最好。
使用IDA分析main函数,main函数的逻辑很简单,依次调用Welcome、ShowMsg,然后通过write打印提示信息,最后通过read读取用户输入数据,通过Check函数来检查输入的Flag是否正确。关键逻辑都在Check函数里边。里面有个嵌套两层的for循环,外层for循环负责对wow中每一个句子进行处理,删除其中不是字母的字符,然后存到一个缓冲区中,关键代码如下:
内层循环中,会遍历输入的flag字符串,然后将flag中的每一个字符与处理后的一句话中的前22个字符分别相乘并求和,关键代码如下:
然后把每次内层循环求得的值如verify数组中的值比较,如果不相等则提示失败,相等则继续循环处理,关键代码如下:
这里要求的就是长度为22的flag字符串了。刚好有22句话,然后两个循环的跨度都是22,所以只会处理前22个字母,另外verify也是22个值,刚好构成一个矩阵的乘法,Python的numpy库提供了对矩阵计算的支持(逆矩阵、矩阵的转置等):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #!/usr/bin/env python # -*- coding:utf-8 -*- import string from numpy import * def getMatrix(): hints = [ "The light! To keep in mind the holy light!\n", "Time is money, my friend!\n", "Welcome to the auger RuiMa!\n", "Are you here to play for the horde?\n", "To arms, ye roustabouts! We've got company!\n", "Ahh... welcome to my parlor.\n", "Slay them in the master's name!\n", "Yes, run! It makes the blood pump faster!\n", "Shhh... it will all be over soon.\n", "Kneel before me, worm!\n", "Run while you still can!\n", "Rise, my soldiers! Rise and fight once more!\n", "Life is meaninglesh; That we are truly tested.\n", "Bow to the might of the Highlord!\n", "The first kill goes to me! Anyone care to wager?\n", "It is... as it should be.\n", "The dark void awaits you!\n", "In order to more glory of Michael essien ray!\n", "Remember the sun the well of shame!\n", "May the wind guide your road!\n", "Strength and Honour!\n", "Blood and thunder!\n" ] res = [] for s in hints: row = [] for ch in s: if ch in string.letters: row.append(ord(ch)) while len(row) < 22: row.append(0) if len(row) != 22: row = row[0:22] res.append(row) return res def printMatrix(m): for s in m: t = [] for ch in s: t.append(chr(ch)) print "".join(t) def crack(): mykey = [ 0x373CA, 0x31BDF, 0x374F7, 0x39406, 0x399C4, 0x34ADC, 0x38C08, 0x38B88, 0x38A60, 0x2B568, 0x32471, 0x37DEA, 0x36F97, 0x378E4, 0x38706, 0x29010, 0x34C23, 0x38EF8, 0x38E29, 0x3925E, 0x2B5FC, 0x2584E ] mymatrix = getMatrix() #print mymatrix #print mykey flag = mat(mymatrix).I * mat(mykey).T print flag def getFlag(): # flag s = [104, 99, 116, 102, 123, 76, 74, 95, 121, 54, 99, 100, 99, 95, 113, 119, 101, 101, 114, 116, 33, 125] res = [] for ch in s: res.append(chr(ch)) print "".join(res) if __name__ == "__main__": # crack() getFlag() # hctf{LJ_y6cdc_qweert!} |
本文地址: 程序人生 >> XCTF HCTF Reverse Writeup
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!