realloc_hook

有时one_gadget因为环境原因全都不可用,这时可以通过realloc_hook来调整堆栈环境。

xxx

将realloc_hook设置为选好的one_gadget,malloc_hook设置为如图某条push指令

注意sub rsp,0x18

从而调整改变栈环境。

因为realloc_hook和malloc_hook相邻,所以有机会同时修改两个值。

通过main_arena获取libc基地址

main_arena储存在libc.so.6的.data段,通过这个偏移我们可以获取libc基地址。

将libc.so.6拖入IDA中,找到malloc_trim()函数

__malloc_trim源码

强行加载不同版本glibc

pwn_debug

pwndocker

通过environ环境变量改写main返回地址

在历史上,大多数unix系统都支持main函数带三个参数,其中第三个参数就是表示环境表的地址,在glibc中储存程序运行需要的环境变量。
int main(int argc,char *argv[],char *envp)

通过 libc.symbols[‘__environ’] 找到environ变量在glibc中的地址,从而确定main函数在栈中的返回地址。

scanf & printf

scanf输入大量字符会调用malloc和free

scanf(“%d”)输入+、- 不会更改栈上的值(比如绕过canary

printf(“%10000c”,x) 当宽度过大时会调用malloc和free

seccomp会调用calloc

pass

绕过seccomp沙盒保护

未检查arch

当未检查arch参数时,可以尝试转换当前的处理器模式。

i386和x86-64拥有有不同的系统调用号,例如在x86_64下禁用了0x3b(execve)号系统调用,那么可以欺骗cpu目前在运行i386的程序,那么就可以使用系统调用号0xb(i386下的execve),当然要求0xb不在黑名单中。

1
2
3
4
5
6
to32:                           
mov DWORD [rsp+4],0x23 ;;将CPU模式转换为32位
retf ;;pop cs:eip
to64:
mov DWORD [esp+4],0x33 ;;将CPU模式转换为64位
retf ;;pop cs:eip

x64下使用X32

如果开启了arch检查,使用X32的方式绕过。

X32为x86-64下的一种特殊的模式,它只工作在原来为64位的程序下,它使用64位的寄存器和32位的地址,此时nr会在原来的基础上加上__X32_SYSCALL_BIT (0X40000000),即原本的sys_number + 0x40000000,这会达到一样的效果。

reference

https://blog.betamao.me/2019/01/23/Linux沙箱之seccomp/

magic gadgets

1
2
3
4
pwndbg> x/10xi 0x0000000000400618
0x400618 <__do_global_dtors_aux+24>: add DWORD PTR [rbp-0x3d],ebx
0x40061b <__do_global_dtors_aux+27>: nop DWORD PTR [rax+rax*1+0x0]
0x400620 <__do_global_dtors_aux+32>: repz ret

这是一个在栈溢出时很好用的gadget,通过csu中的通用gadgets可以控制rbx,在使用one_gadget时加上参数-l 2,可以找到一个要求r12 r14为0的rce,因为csu我们可以轻易控制这俩参数,十分好用。甚至不需要leak就可以getshell,如果Partial RELRO 那么直接add GOT 通过计算偏移修改为rce;如果Full RELRO,那么通过返回到libc_start_main会在栈上写入libc地址也可以利用。cscctf_2019_quals_signal

1
2
3
0x7ffff7f197a0 <getkeyserv_handle+576>:	mov    rdx,QWORD PTR [rdi+0x8]
0x7ffff7f197a4 <getkeyserv_handle+580>: mov QWORD PTR [rsp],rax
0x7ffff7f197a8 <getkeyserv_handle+584>: call QWORD PTR [rdx+0x20]

这是一个存在与glibc2.31的gadget,因为在此版本的setcontext参数被改为了rdx,那么可以通过这个gadget再次实现利用。2020_GACTF_card。另外提一下glibc2.29后vtable可写

reference

https://publicki.top/2020/06/17/cscctf_2019_qual_signal/

libc.got[‘__free_hook’]

1
2
3
4
  0x7ffff7a9154a <free+10>     mov    rax, qword ptr [rip + 0x33f9a7]
► 0x7ffff7a91551 <free+17> mov rax, qword ptr [rax]
0x7ffff7a91554 <free+20> test rax, rax
0x7ffff7a91557 <free+23> jne free+240 <0x7ffff7a91630>

free时会先拿出free_hook@got的值,再判断这里面是否为空