-
-
[原创]红帽杯2019
-
2022-5-20 23:18 14971
-
ChildRe
先输入字符串
下边判断长度等于31
sub_7FF74A631280输出字符串首字母,放在v4
sub_7FF74A6315C0用递归遍历字符串并改变顺序存在name里
这里的遍历其实是二叉树遍历还是后序的
输入字符串: 1234567890abcdefghijklmnopqrstu
输出字符串: fg8hi94jk0lma52nobpqc6rsdtue731
Abcdeabcdeabcdeabcdeabcdeabcdez
下边是变换后的顺序
判断v9等于62
将a1234567890Qwer字符串与0x7FF655C93478和 0x7FF655C93438i64
两个字符串比较判断
用outputString的值除和取余操作后作为a1234567890Qwer角标
1 2 3 4 5 6 7 8 | s3478 = "(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&" s3438 = "55565653255552225565565555243466334653663544426565555525555222" s = '1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;,ASDFGHJKL:"ZXCVBNM<>?zxcvbnm,./' p = '' for i in range ( 62 ): p + = chr (s.find(s3478[i]) + s.find(s3438[i]) * 23 ) print (p) |
P= private: char __thiscall R0Pxx::My_Aut0_PWN(unsigned char )
此脚本提取满足判断条件的a1234567890Qwer的输入字符串
但是md5提交后发现不对
重新审计代码
outputString在UnDecorateSymbolName函数中被改过
此函数是去掉C++函数名修饰
根据此规则还原函数修饰:
?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z
这里看到函数修饰字符串由v5得来,所以outputSring是输入值的后序遍历
结果:Z0atRAEyup@XAAA?M_A0_WNPX@@EPDP
第二种解法
这个脚本是对二叉树的逆序解释
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <string.h> int main() { char name[ 32 ] = "?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z" ; int biao[] = { 0x50 , 0x51 , 0x48 , 0x52 , 0x53 , 0x49 , 0x44 , 0x54 , 0x55 , 0x4a , 0x56 , 0x57 , 0x4b , 0x45 , 0x42 , 0x58 , 0x59 , 0x4c , 0x5a , 0x5b , 0x4d , 0x46 , 0x5c , 0x5d , 0x4e , 0x5e , 0x5f , 0x4f , 0x47 , 0x43 , 65 }; char input [ 32 ] = { 0 }; int i; for (i = 0 ; i < strlen(name); i + + ) input [biao[i] - 65 ] = name[i]; puts( input ); return 0 ; } |
EasyRe
第一次输入
Sub_4406E0是输入函数,要求输入长度为36个字符
下边是一个循环异或,v12在动态调试下给出
脚本
1 2 3 4 5 6 7 8 | v12 = [ 73 , 111 , 100 , 108 , 62 , 81 , 110 , 98 , 40 , 111 , 99 , 121 , 127 , 121 , 46 , 105 , 127 , 100 , 96 , 51 , 119 , 125 , 119 , 101 , 107 , 57 , 123 , 105 , 121 , 61 , 126 , 121 , 76 , 64 , 69 , 67 ] flag = '' for i in range ( len (v12)): flag + = chr (v12[i] ^ i) print (flag) |
通过脚本得到第一次输入的字符串为Info:The first four chars are flag
第二次输入
第二次输入到v51,经过十次sub_400E44(base64)的结果放到Sub_400360与off_6cc090比较
结果正确那么输出字符串'you find me'
脚本
1 2 3 4 5 | import base64 lis = “ 这里放数组” for i in range ( 10 ): lis = base64.b64decode(lis) print (lis) |
通过这个脚本10次base64反编码解得一个网址:https://bbs.pediy.com/thread-254172.htm
但是依然不是flag
唯一有用的函数
可以看出这个函数是.fini节调用
main的返回地址是libc_start_main也就是说main并不是程序真正开始的地方,libc_start_main的执行是在main的前面。
可以发现libc_start_main函数的参数中有三个指针
libc_csu_fini是在main执行完毕后执行的,之前分析的程序与__libc_csu_fini内的函数没有关系
V8与byte_6cc0a0第一项和第三项异或得到 'f’, 'g’
那么v8与byte_6cc0a0异或就是flag
所以'flag'与byte_6cc0a0前四项异或得到v8
V8是int型拆分成四个char型字符成为数组与byte_6cc0a0循环异或
1 2 3 4 5 6 7 8 9 10 11 | key = '' enc1 = 'flag' dec = '' enc = [ 0x40 , 0x35 , 0x20 , 0x56 , 0x5D , 0x18 , 0x22 , 0x45 , 0x17 , 0x2F , 0x24 , 0x6E , 0x62 , 0x3C , 0x27 , 0x54 , 0x48 , 0x6C , 0x24 , 0x6E , 0x72 , 0x3C , 0x32 , 0x45 , 0x5B ] for i in range ( 4 ): key + = chr (enc[i] ^ ord (enc1[i])) print (key) for i in range ( len (enc)): dec + = chr (enc[i] ^ ord (key[i % 4 ])) print (dec) |
flag脚本结果:flag{Act1ve_Defen5e_Test}
博客: https://qwer597.github.io/
hello
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课