ღ Miranda

pwnable.kr的PWN挑战之Toddler’s Bottle(二)

pwnable.kr is a non-commercial site which provides various pwn challenges regarding system exploitation. the main purpose of pwnable.kr is fun.

refer:
https://gist.github.com/ihciah/0ca68da3e32e38818bb9
http://rickgray.me/2015/07/24/toddler-s-bottle-writeup-pwnable-kr.html
http://weaponx.site/2017/02/21/unlink-Writeup-pwnable-kr/
https://github.com/Qwaz/solved-hacking-problem/tree/master/pwnable.kr

random-1pt

rand()函数不指定seed的话每次生成的随机数都是一样的,所以可以在本地运行一下,发现这个数值是1804289383:

然后和0xdeadbeef异或得到要输入的数字:

input-4pt

Stage 1

要求有100个命令行参数,argv['A']也就是第65个参数为"\x00",第66个为"\x20\x0a\x0d",由于这题要输入的比较多,所以最好写一个C程序输入,用execve()函数运行input:

程序如下:

输出:

stage 2

int memcmp(const void *buf1, const void *buf2, unsigned int count);是比较内存区域buf1buf2的前count个字节,该函数是按字节比较的,buf1、buf2为字符串时候memcmp()就是比较前count个字节的ascII码值。read(0, buf, 4);表示从标准输入读取4 bytesbuf中,要为"\x00\x0a\x00\xff",看实例:

read(2, buf, 4);表示从标准错误流读入,其实这两个可以一起用pipes实现,用两个pipes,一个stdin,一个stderr,可以参考http://unixwiz.net/techtips/remap-pipe-fds.html

目前的代码为:

stage 3

这个可以将自己定义的env传递给execve()的的三个参数,env定义为:

stage 4

“\x0a”这个文件名为不可打印字符,要创建并写入4 bytes:

stage 5

首先创建了套接字,然后argv['C']指定了监听端口,并且要求接收到的前四个字节为\xde\xad\xbe\xef

最终程序如下:

然后在远程服务器上的/tmp目录下创建C程序并编译:

leg-2pt

题目给出了C源码和一份反汇编码:

由源码看出输入的key值为三个函数返回值之和,下面看汇编代码:

注意看三个函数的返回值都在r0寄存器里,一个一看。

key1:

最终r0里的值为pc里的值,PC代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:1.取指(从存储器装载一条指令),2.译码(识别将要被执行的指令),3.执行(处理指令并将结果写回寄存器)。而R15(PC)总是指向正在取指的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定将“正在执行的指令作为参考点,称之为当前第一条指令,因此PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址 加8字节的地址,即:PC值=当前程序执行位置+8。所以这里pc8cdc+8=8ce4。即key1()返回8ce4

key2:

bx r6的作用等同于mov pc,r6,这里r0最终为r3的值,0x00008d04处的pc值赋给了r3,然后r3加了4bx r6r6地址处切换成thumb模式。进入thumb指令模式有两种方法:一种是执行一条交换转移指令bx,另一种方法是利用异常返回,也可以把微处理器从arm模式转换为thumb模式。退出thumb指令模式也有两种方法:一种是执行thumb指令中的交换转移bx指令可以显式的返回到arm指令流。另一种是利用异常进入arm指令流 。在thumb模式下pc = 当前地址+4。所以最后r08d04+4+4=8d0c

key3:

返回结果是lr寄存器的值,lr就是连接寄存器(Link Register, LR),在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。主函数中bl 0x8d20 <key3>bl指令调用了key3()函数,BL指令在转移到子程序执行之前,将其下一条指令的地址拷贝到R14(LR,链接寄存器),所以这里lr里为返回地址8d80

最后加起来换成十进制为108400:

mistake-1pt

函数读取十位的输入,经过xor()函数后与password文件里的密码比较,正确就输出flag,但password文件不可读,注意这里:

题目提示是运算符优先级的问题,<的优先级高于=,看下面的程序:

文件存在则输出为0,所以read(fd,pw_buf,PW_LEN)这句读取文件的语句实际是从输入流读入了10个字节的密码。所以很容易构造:

shellshock-1pt

由题目提示,shellshock又称Bashdoor,是在Unix中广泛使用的Bash shell中的一个安全漏洞,首次于2014年9月24日公开。许多互联网守护进程,如网页服务器,使用bash来处理某些命令,从而允许攻击者在易受攻击的Bash版本上执行任意代码。这可使攻击者在未授权的情况下访问计算机系统。判断方法为执行命令env x='() { :;}; echo Shellshock' bash -c "exit",如果有输出,就说明存在该漏洞,检查目录下bash的版本为有漏洞的版本,直接可以构造payload:

coin1-6pt

nc pwnable.kr 9007后可以看到游戏规则,就是一个二分法的题目,要在30
s
内解100次就会有flag,题目提示用任意账号连到服务器上跑脚本,脚本如下:

/tmp目录下创建脚本并执行就能得到flag:

blackjack-1pt

这题源码在http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html,读源码发现在玩家输入下注金额时没有判断负数,所以可以简单地输入-$1000000为下注金额,然后输掉比赛就可以达到总金额$1000000的条件:

lotto-2pt

要求输入六个数字与随机的六个数字完全一样,但判断这里循环了36次,也就是输入六个一样的字符,有一个相同就行了,几率还是比较大的,多试几次,比如一直输(((((((:

cmd1-1pt

strstr(str1,str2)函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2str1中首次出现的地址;否则,返回NULLint putenv(char *envvar)用来改变或增加环境变量的内容。参数envvar的格式为envvar=value,如果该环境变量原先存在,则变量内容会依参数envvar改变,否则此参数内容会成为新的环境变量。参数envvar指定的字符串会变成环境变量的一部分,如果修改这个字符串,环境变量也会跟着被修改。题目修改了环境变量,导致不能直接用cat命令,但可以用/bin/cat代替,不能出现flag字段,可以用通配符绕过:

cmd2-9pt

这题的函数过滤了更多的字符,而pwd命令可以直接产生/,从而可以绕过过滤,可以在/tmp目录下创建文件夹/tmp/my/c,然后在/tmp/my下创建/bin/cat的软连接,然后在/tmp/my/c下创建flag文件的软连接:

\转义了/防止在程序中被当做命令先执行了,这样就会被过滤:

  1. cleanmymac 3.9 key说道:

    Great, google took me stright here. thanks btw for info. Cheers!

发表评论

电子邮件地址不会被公开。