PlaidCTF-2014-hudak-Writeup

说明:

hudak-Reversing (250 pts) Can you reverse this program and find out
what The Plague was working on?

把程序拖入IDA和EDB中围观
pctf01.png
IDA看该程序,首先判断字符串长度是不是30,不是直接跳转到wrong。动态跟踪程序发现,实际需要输入29个字符,程序会自动在字符串末尾加上FF。
输入满足长度的字符即可继续。
程序流程就是检查正确了就跳到Congratulations,于是跟入其上方的函数。
pctf02.png
进入sub_80489f0
pctf03.png
看到memcmp比较字符串,相等,返回0,eax置为1。即可跳转到Congratulations。
跟入sub_80486e0
pctf04.png
它首先在0x8048810里由原字符串产生一系列子串(我也不知道该不该交子串),类似于输入字符串为plaid,它就会产生plaid,laidp,aidpl,idpla,dplai这5个子串,我们输入的字符串长度为29+1=30(29个自己输入的字符加上一个程序在字串末尾加上的FF),因此共有30个子串。
并将指向这些子串的指针按照上述例子的顺序,放到一段buf里,构成一张包含所有子串地址的表(字符串地址表)。
pctf05.png
接下来对刚刚产生的字符子串进行排序,利用冒泡排序法从小到大排序,产生新的字符串地址表,这时该表中的各个子串地址的顺序,是由小到大的。
pctf06.png
至此,0x8048810返回新字符串地址表(返回到sub_80486e0中)
继续loc_8048748,程序按照排序后的字符串地址表中的顺序取每个字符串的最后一个字符,对其与0x37异或,得到异或后的30个字符(因为共30个子串)。
pctf07.png
将异或后的字符串返回到sub_8048f0中,即为S2,与S1比较,其中S1为固定在程序内的字符串,相等则返回0,则可以跳转到congratulation。
pctf08.png
程序流程大致如上。


下面是解题思路:
将固定字符串S1异或,得到29个字符,也就是组成key的29个字符,但由于程序是将输入字符串的30个子串按从小到大排序后取最后一个字符,构成S2的,因此按固定在程序中的字符串s1的顺序不能直接确定key。
此时发现S1字符串中C8这一字节与0x37异或之后为FF,它在S1字符串的第9位。前面提到过,程序会在你输入的字串后加上一位FF。也就说明S1字符串的 第9位的字符 是由我们输入的字符串的原始顺序的最后一位,也就是说 如果输入字符串为plaid,那么在排序后的字符串地址表中,第9个地址的字符串为原始顺序即为plaid这个顺序。因此,我们原始顺序的字符串开始的第一个字母,一定是字符串中第9小的数,开始,即为4(ascii 0x34)。但字符集中有两个4,第8位和第9位,若想在第9位出现FF,则4(第9位)后面跟的字符一定要比4(第8位)后面跟的字符大。
若要第一个字符为3,则3所在的字符子串一定是最小的字串,因此该子串的第一个字符一定是最小的即0x2E(“.”),由于3取的是该子串最后一个字符,则0x33(“3”)一定在0x2E(“.”)前面。
也就是说,表1中字符后面跟的字符,为该字符所在位置标号的数对应表2中的字符,(肿么说出来这么绕嘴,就是这个字符在第几位它后面就跟第几小的数)
如(0x33后需跟第1 小的数(最小的数)即 0x2E,因为33排在表1的第1位)
S1与0x37异或后
pctf09.png
将异或后的字符 按照从小到大的顺序排列
pctf10.png
中途的问题,就是有多个相同的字符选哪个的问题,手工广度优先搜索,排到某个数据的时候发现该字符已用完,表示本条路不通。
几番周折之后,加上联想几个英语单词,组合拼装了一下,
终于拿到了FLAG:4t_l34st_it_was_1mperat1v3…
经某熊的指点,程序应该向下面那样
程序要求:在表一中读取数据,按其位置编号在表二中搜索,并检查表二中该编号对应的字符是否有多个(n个),若有则分n中情况继续向下搜索,当所寻找的表二中的编号已被用过,则表示该顺序错误,停止该种情况的搜索,直到找出29个字符的字符串为止。

@to1ight ::TEAM L::

tagged by pctf reverse  

Comment Closed.

© 2014 ::L Team::