BUUCTF/RE/刮开有奖!!!!
这题一开始我以为是动调修改弹出框,我以为dialogbox删掉之后会显示出其他被挡住的弹窗(所以才说刮开有奖啊!)结果把dialogbox搞掉之后仍然没有弹出,甚至我都跳转不到messagebox的地方。。
呜~思路失败,润去看别人题解,发现居然是ida逆向qaq 一开始看见ida那么多函数而且没有main函数(呜我只认识main函数),而且一开始先入为主觉得肯定是动调解决问题,字符串也没仔细看,漏掉了信息qaq
现在我用OD实在解决不来问题 qaq 总之我退让了,打开了IDA(倒下
在动调的时候我其实发现了messagebox里放了奇怪的东西:U get it~,正因此我一直以为只要打开了messagebox就能得到flag
IDA的字符串里确实有U g3t 1t,点进去一看发现是一串加密函数。
按照惯例先总览一下↑:首先给出了很多数据,然后对String这个数组进行各种赋值变换,最后用if语句进行check
然后分步往下看:
这个a2只有三处引用,联系到这个是dialog函数,加上参数名字其实也在暗示a2应该只是跟对话框有关的一个数据,具体是什么不管它,反正为了运行到“U g3t 1T”这里,肯定不会被return的。
继续往下看:
memset把String清零,虽然数值很大但没关系,最后if函数比较的语句也就那么几句而已。
下一句是个API,搜了一下用法,常见的用法是让用户输入账号密码之类的,感觉类似scanf,那么input就是这个String了,一般来说我的input就是flag了。
接下来是一个sub_4010F0函数,点进去看看:
这里我修改了一下变量的名字,在原名后面下划线加上了传参的数字。这里的v7是个数组,v7[0]=90,我的理解是传v7的首地址也就是v7[0]上的数值进去了。所以v7在这里等于90。也正是因为这里的v7对应着外面v7[0]的地址,所以这个函数必须关注,因为外面checkflag的时候会用到v7[0],也就是说这个函数影响最终check的数据。
下面这段带循环的代码,有很多4*某个数,一开始让我有点怀疑是什么游戏。。数据都给了,那就模拟走一遍。
这里模拟的写法我搞的太烂了,一开始忘记它有一个对自身的再调用(LABEL13)所以模拟直接写在main函数里了,把v7直接赋值90,然后修改了很多处关于v7的运算语法(
运行发现结果错了,才意识到再调用没改,然后又重新写函数+main函数,呜改了半天还是有小错,很多地方含糊不清,润去看题解了。
看完题解咯~!感觉这题欠缺的不是读不懂,而是我太轴了,通篇读完又人脑模拟了半天才意识到可以用电脑模拟。看完题解之后发现了一个问题,就是v7v8等等一大串变量,他们的地址是相邻的,也就是说*v7[1]+4=v8这样的。这里+4是因为int类型占据四个字节,或者从内存地址上也能看出来,不过我一开始真的没看出来qaq。其实这样不同变量却连续地址的情况,以前也见过一次,但我以为那个是意外呢。。qaq 看来可能是IDA识别的时候会出问题,以后进入IDA还得加上一个新习惯,就是去看看变量的地址,尤其是在这种函数里对参数取地址再运算的情况,变量的地址绝对有猫腻,我太傻了,呜…而且要关注地址之间的差值,比如这次差值是4,这样才能搞懂运算里的*4是什么含义。
这次脚本的写法也是我第一次见,虽然模糊的想到了怎么写,但细节上一直出错。简单来说就是把主函数调用这块函数的地方单独写出来,然后函数内部基本上照抄即可。也就是尽量模仿IDA给出的伪代码进行还原。这样做的好处是不容易出错,思路清晰。毕竟这只是让程序运行起来看看结果。写到这里突然意识到或许这里是真的可以动调,然后直接断点拦截看看结果的(可恶
看了题解之后还有一个新收获:
char数组里如果直接放0-256这些数字,意味着是ascii码。除非加上引号,否则char是不会认为这是字符的。qaq我的基础知识不堪一击。。脚本在这里就不放了,因为是看了别人的答案写出来的qaq直接上答案:
接下来放个小整体:分别把String数组的某几位赋值给一个三位数组v18, 进行两次运算,得到了v5和v4的值,在后续和两个字符串进行比较。
v4和v5的结果已知,那么它原先是什么样子呢?也就是说,生成v4和v5的那几个String[]值是多少呢?
v5很好办,因为通过if的前四条语句,我们可以知道String[0 1 2 3]分别是多少了,把数值代入sub_401000暴力运算即可。但是v4怎么办呢?还是得认真分析sub_401000啊~
这函数好复杂qaq但是里面有一个怪怪数据,也是图上标黄的地方。点进去:
一般遇见长串“乱码”都很值得关注一下
41h对应的字符是A,这份数据全是base64认得的那些字符,查一下base64的算法:(11条消息) Base64 编解码的C语言实现_用心看,这个世界好奇妙,代码也很奇妙-CSDN博客_c语言实现base64
然后就很明白啦,这段代码具体写了什么我不知道,也不在乎,我只知道它先/3,又对3取模,然后进行了位运算,最后从byte_407830里找出对应的字符。和base64的算法完全对的上。
那么直接拿结果去解码啦:
567对应jMp,234对应WP1
01通过if的check算一下:51+34='U';v10是之前脚本运行结果第五位J
flag就出来啦,是一句经典的台词:u jump,i jump!
flag{UJWP1jMp}