ctf中关于syscall系统调用的简单分析

访客3年前黑客工具511

  01

  0x01

  我在动态调试这个程序的时候,发现 syscall调用 系统函数 的过程很有趣,于是便记录下来 希望对大家 能带来些帮助,这里 以 buu 平台上的 ciscn_2019_s_3 为例,给大家详细地分享以及分析下!

  02

  0x02

  在开始之前,我们先来认真 学习下 read(),write()的 原型:

  03

  0x03

  然后我们再来简单了解下 syscall !嗯...我们来看下 *** 的介绍吧,

  

  上面的是 32 位的系统调用,而64位系统的系统调用总体思想还是一样的,当然也会有些不同,

  32位与64位系统调用的区别:

  1. 传参方式不同

  2. 系统调用号 不同

  3. 调用方式 不同

  32位:

  传参方式:首先将系统调用号 传入 eax,然后将参数 从左到右 依次存入 ebx,ecx,edx寄存器中,返回值存在eax寄存器

  调用号:sys_read 的调用号 为 3 sys_write 的调用号 为 4

  调用方式: 使用 int 80h 中断进行系统调用

  64位:

  传参方式:首先将系统调用号 传入 rax,然后将参数 从左到右 依次存入 rdi,rsi,rdx寄存器中,返回值存在rax寄存器

  调用号:sys_read 的调用号 为 0 sys_write 的调用号 为 1

  stub_execve 的调用号 为 59 stub_rt_sigreturn 的调用号 为 15

  调用方式: 使用 syscall 进行系统调用

  Ok,知道了上面这些知识,那么做这题,其实相对来说 会容易些了!可能本来大佬们就没觉得难,还求勿喷!基于网上 对这题的题解很少,我调试了很长时间才弄懂!实在是太弱了!

  04

  0x04

  首先检查文件属性和文件开启的保护有哪些:

  64位elf 文件 只开启 NX 保护

  拖入ida 查看main函数:

  嗯。。。我们看汇编代码!

  

  这里可以看到 汇编指令 的含义

  -----------------------------------------------------

  将read的系统调用号 0 赋值给 rax

  将 read的之一个参数0 (fd) 赋值给了 rdi

  将 read的第二个参数 buf 赋值给了 rsi

  将 read的第二个参数 buf 赋值给了 rdx

  即系统调用了 read(0,&buf,0x400)

  同理 紧接着 又调用了 write(1,&buf,0x30)

  其中 buf 距离 rbp 0x10个字节,存在栈溢出漏洞!

  

  然后经过调试 我还发现当执行了 syscall这个汇编命令(即调用对应系统函数)后,

  在gdb上可以很清楚的 看到 其实执行完后 对寄存器的影响

  仅仅发生改变的是RAX,与RCX

  其中 RAX 会存着 对应系统函数 调用后返回的结果

  RCX 会存着当 syscall指令的下一条指令地址

  这里放个对比图,可以看的更明白些!

  syscall指令 执行前:

  

  syscall指令执行后:

  

  当然,知道这些对于我们来说已经足够了!

  我们继续来分析下 vuln函数 ,具体看下图中注释

  

  这个题rsp和rbp一直在重合,直接ret,就相当于pop rip,

  所以覆盖rbp就可以劫持了程序执行流。

  所以 这题 在最后 ret的 时候其实 就是 返回 到了rbp处 的地址了。这点很重要。

  -----------------------------------------------

  另外程序中还有个gadgets 函数

  

  我们可以 发现这个函数里面有两个可以 gadget 即 控制 rax的 带有 ret 的汇编指令片段

  mov rax,0Fh // 0Fh 即15 而15 对应的是 sys_rt_sigreturn系统调用

  mov rax,3Bh // 3Bh 即 59 而15 对应的是 sys_execve 系统调用

  对于 以上两个系统调用,我们可以有两种 解题 ***

  之一种:利用 ret2__libc_csu_init 去构造 execve("/bin/sh",0,0) 来 getshell

  第二种:直接srop 伪造 sigreturn frame 去 构造 execve("/bin/sh",0,0) 来 getshell

  我们重点 就看之一种 了:

  因为是系统调用嘛,

  所以我们要想 构造 execve("/bin/sh",0,0) 需要

  将 sys_execve 的调用号 59 赋值给 rax

  将 之一个参数即字符串 "/bin/sh"的地址 赋值给 rdi

  将 第二个参数 0 赋值给 rsi

  将 第三个参数 0 赋值给 rdx

  但我们发现 我们没有 足够gadget 可以利用,于是我们想到了

  “x64 下的 __libc_csu_init 中的 gadgets,这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在“

  用下面这个命令去 找到它的位置,

  ROPgadget --binary ciscn_s_3 --only 'pop|ret'

  

  这里需要注意 Ropgadget 有时总会 有一点显示的不完整,我们通过它在ida中再去看下,

  loc_400580和loc_400596 就是上面说的 __libc_csu_init gadget了。

  

  05

  0x05

  我们最终写下如下 exp:

  06

  0x06

  我们照着 exp 来分析下 :

  解答1:

  因为最后我们构造payload的时候需要用到 /bin/sh 的地址,程序中又没有,我们这里选择自己输入,但是我们输入到了 栈上,为了后面可以使用该 地址,我们需要首先将 /bin/sh 所在栈地址 泄露出来!

  我们gdb调试,可以得知 在write输出的 0x20字节后 的 0x00007fffffffde08 是栈 上的地址 我们用它 减去 buf 所在栈上地址 即可得到 /bin/sh所在栈上地址 0x00007fffffffde08-0x7fffffffdcf0=280

  反之 bin_sh_addr=0x00007fffffffde08-280

  

  解答二 :

  为什么要这样构造 payload2?

  payload2='/bin/shx00'*2+p64(pop_rbx_rbp_r12_r13_r14_r15_ret_addr)+p64(0)*2+p64(bin_sh_addr+0x50)+p64(0)*3

  payload2+=p64(__libc_csu_init_addr)+p64(mov_rax_execv_addr)

  payload2+=p64(pop_rdi_ret_addr)+p64(bin_sh_addr)+p64(syscall_addr)

  看这个payload的之一行:

  因为文章上面我已经分析过了

  ******************************************************************************************

  这个题rsp和rbp一直在重合,直接ret,就相当于pop rip,

  所以覆盖rbp就可以劫持了程序执行流。

  所以 这题 在最后 ret的 时候其实 就是 返回 到了rbp处 的地址了。于是 p64(pop_rbx_rbp_r12_r13_r14_r15_ret_addr) 其实就相当于是在ret_addr处,

  **************************************************************************

  

  看图,动态来具体了解下 这个payload是怎么运转的我们跟进去

  

  继续 n 我们会返回到 __libc_csu_init_addr 0x400580

  

  如图:将execve 的系统调用号 0x 3b 赋值给 rax

  

  执行完后会 ret 回到 add rbx,0x1

  这里是很关键的一步,

  原本 rbp=rbx=0,然而 rbx在这 加了 1 与 rbp就不再相等 于是 会跳转到0x400580执行

  

  call QWORD PTR [r12+rbx*8] 便会 调用了 红框之后的 pop_rdi_ret_addr 处的函gadget了

  

  然后接着就是 把 bin_sh_addr 赋值给了 rdi了

  这样 execve("/bin/sh",0,0)就构造成功了,最后再执行syscall_addr便成功调用该函数 于是getshell 。

  

  这里如果 还理解不了的话 可以在ctf_wiki学习下栈溢出之 medium_rop

  

  07

  0x07

  第二种:直接srop 伪造 sigreturn frame 去 伪造 execve("/bin/sh",0,0) 来 getshell

  具体就是 首先利用 mov rax, 0Fh 控制rax为 15,然后 调用 syscall 即执行了 sigreturn,我们 伪造 sigreturn frame 去 执行 execve("/bin/sh",0,0) 即可

  最后要注意的一点就是 写 exp 时一定要 说明 内核架构 不然报错!

  context(arch='amd64', os='linux', log_level='DEBUG')#这个注意一定要说明内核架构 ,不然报错。

相关文章

怎么同时吸收老公微信不被发现,教你怎么恢复聊天记录!

许多电脑软件在安装的时刻都市强制安装种种捆绑软件,甚至是弹窗广告,就连着名的腾讯QQ、搜狗输入法这种大公司软件都是天天都弹广告,就更别提一些通俗软件了。那么,怎样阻挡电脑弹窗广告?许多同伙对于弹窗广告...

飞雕开关怎么样

飞雕开关怎么样

  在开关类十大品牌排行榜之中,除了我们熟知的公牛,尚有飞雕。这个品牌论起来算是海内较量早开始做开关插座的厂商,公司涉足的尚有家产电气,灯饰照明,等等,可谓是琳琅满目,只要装修用的产物在它的店里都可以...

零基础黑客教程(黑客基础菜鸟入门教程)-求真实网络黑客

零基础黑客教程(黑客基础菜鸟入门教程)-求真实网络黑客

零基础黑客教程(黑客基础菜鸟入门教程)(tiechemo.com)一直致力于黑客(HACK)技术、黑客QQ群、信息安全、web安全、渗透运维、黑客工具、找黑客、黑客联系方式、24小时在线网络黑客、黑客...

找黑客帮忙平台-哪里找黑客可靠(网上收费的黑客可靠吗)

找黑客帮忙平台-哪里找黑客可靠(网上收费的黑客可靠吗)

找黑客帮忙平台相关问题 黑客查信息可靠吗相关问题 黑客为什么能闯入别人的电脑 黑客怎么用网站看用户信息(黑客论坛网站源码)...

去哪找黑客做事(去哪找黑客)-伪装黑客代码

去哪找黑客做事(去哪找黑客)-伪装黑客代码

去哪找黑客做事(去哪找黑客)(tiechemo.com)一直致力于黑客(HACK)技术、黑客QQ群、信息安全、web安全、渗透运维、黑客工具、找黑客、黑客联系方式、24小时在线网络黑客、黑客业务、黑客...

感同身受什么意思(关于感同身受的句子)

感同身受什么意思(关于感同身受的句子)

1. 别把自己想的太伟大,要知道,在别人的世界里,不管你做的多好,你都只是个配角而已。 2. 人越长大话越少,我们不再说今天受了委屈,不再说谁谁谁不理我了我好难过,不再分享生活中的琐事。我知道人和人...