AWD pwn备忘

1
socat tcp-l:9999,reuseaddr,fork exec:./blind_note &

通防

原理:通过LD_PRELOAD加载自定义的so文件,hook危险函数。

1
2
$LD_PRELOAD=./libdheap.so LIBDHEAP_EXIT_ON_ERROR=1 ./pwn #heap
$LD_PRELOAD=./libdprintf-x64.so ./pwn #printf
1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <unistd.h>
int main(int arg,char **args)  
{  
  
    char *argv[]={"test",NULL};
	char *envp[]={"LD_PRELOAD=./libdheap.so", "LIBDHEAP_EXIT_ON_ERROR=1",NULL};
    execve("./test",argv,envp);
}

针对漏洞打patch

  • 利用IDA脚本keypatchjmpcall等不能采用freesub_xxxxloc_xxxx的形式,即keypatch不能识别符号地址跳转,要手动指定十六进制地址,但对于ds:note[rax*8]段寻址方式是可以直接识别。
  • 跳转地址计算方法:到达高地址:offset = target - (start + 5) ;到达低地址:offset = 0xffffffff - (start - target) + 1 - 5,如果是printfscanf等这类的库函数,并且在程序中有它的PLTGOT结构,那么把对应的PLT当作target进行计算即可。
  • 大部分 ELF 程序都有一个.eh_frame,这个段的是编译器自己添加进去的,当代码中包含异常处理操作时就会生成,它的主要作用时描述如何卸载stack。一般情况下,程序正常运行的时候是不会触发异常处理代码的,于是这个段就可以作为保存patch代码的空间。

栈溢出漏洞

将输入的长度修改为输入缓冲区大小。

格式化字符串漏洞

方法一:存在puts函数时,将printf直接替换为puts。找到puts函数的plt表地址,将call printf的plt表地址,改成puts的地址。缺点:puts函数会自动在输出的字符串尾部加入一个回车符,某些情况下导致check脚本不通过。

方法二:加%s参数。在.eh_frame段中填入%s字符串,假设地址为0x400c01,将mov edi, offset format,修改为mov edi offset 0x400c01, mov rsi offset format

堆UAF漏洞

增加.eh_frame段的可执行权限,根据readelf --segments getshell,找到.eh_frame段是第几个table_element,如果没有可执行权限。利用010Editor打开,选择Templates->ELF,program_header_table,找到对应的table_element(一般p_vaddr_VIRTUAL_ADDRESS为0x402000,program_table_element[4]),将p_flags修改为PF_Read_Exec(5)

call free修改为跳转到.eh_frame地址jmp 0xf50,然后在.eh_frame上布置将指针置空的指令

call 0x900; #调用free函数plt
mov eax, [rbp-0xc];
cdqe; #使用eax的最高位拓展rax高32位的所有位
lea rdx, ds:0[rax*8];
lea rax, qword ptr [heap];
mov r8,0; #段地址不能直接赋予立即数,借助r8寄存器
mov [rdx+rax],r8;
jmp 0xD56; #跳回正常逻辑

#如果是ptr在bss
.bss:0000000000202050 ptr 
.eh_frame:0000000000000F58 
mov [rip+0x2010f1], rax #0x2010f1 = 0x202050-0xf58 - 7 (7是本语句长度)

gets 栈溢出

只有gets函数能够接受用户输入时,将流程劫持到.eh_frame段,利用syscall构造read函数,就能控制输入数据的长度。

.eh_frame:0000000000400F7D mov     rax, 0          ;#define __NR_read 0
.eh_frame:0000000000400F84 mov     rdi, 0          ; fd
.eh_frame:0000000000400F8B lea     rsi, [rbp+buf]  ; buf
.eh_frame:0000000000400F8E mov     rdx, 90h        ; count
.eh_frame:0000000000400F95 syscall
.eh_frame:0000000000400F97 jmp     loc_400AB4

负数绕过

cmp     eax, 20h
jle     short loc_8048777

输入负数-1也满足jle,修复方法:将JLE改为JBE

  • JA ;无符号大于则跳转
  • JNA ;无符号不大于则跳转
  • JAE ;无符号大于等于则跳转 同JNB
  • JNAE ;无符号不大于等于则跳转 同JB
  • JB ;无符号小于则跳转
  • JNB ;无符号不小于则跳转
  • JBE ;无符号小于等于则跳转 同JNA
  • JNBE ;无符号不小于等于则跳转 同JA

控制if包含范围

修改js/jg跳转的偏移值,使之包含范围改变。