Skip to content

Instantly share code, notes, and snippets.

@soez
Last active September 13, 2022 18:35
Show Gist options
  • Save soez/52864a25603ea4386750442cd020227e to your computer and use it in GitHub Desktop.
Save soez/52864a25603ea4386750442cd020227e to your computer and use it in GitHub Desktop.
# Glibc 2.35 Ubuntu 22.04
When exit is called, it passes by here... (Explaining without ASLR)
0x7ffff7daa390 <__run_exit_handlers>: endbr64
0x7ffff7daa394 <__run_exit_handlers+4>: push r15
0x7ffff7daa396 <__run_exit_handlers+6>: push r14
0x7ffff7daa398 <__run_exit_handlers+8>: push r13
0x7ffff7daa39a <__run_exit_handlers+10>: push r12
0x7ffff7daa39c <__run_exit_handlers+12>: mov r12,rsi
0x7ffff7daa39f <__run_exit_handlers+15>: push rbp
0x7ffff7daa3a0 <__run_exit_handlers+16>: mov ebp,edi
0x7ffff7daa3a2 <__run_exit_handlers+18>: push rbx
0x7ffff7daa3a3 <__run_exit_handlers+19>: sub rsp,0x28
0x7ffff7daa3a7 <__run_exit_handlers+23>: mov DWORD PTR [rsp+0x1c],edx
0x7ffff7daa3ab <__run_exit_handlers+27>: test cl,cl
0x7ffff7daa3ad <__run_exit_handlers+29>: jne 0x7ffff7daa5c4 <__run_exit_handlers+564>
0x7ffff7daa5c4 <__run_exit_handlers+564>: call 0x7ffff7daad60 <__GI___call_tls_dtors>
0x7ffff7daa5c9 <__run_exit_handlers+569>: jmp 0x7ffff7daa3b3 <__run_exit_handlers+35>
0x7ffff7daa3b3 <__run_exit_handlers+35>: lea r14,[rip+0x1d5b2e] # 0x7ffff7f7fee8 <__exit_funcs_lock>
0x7ffff7daa3ba <__run_exit_handlers+42>: xor eax,eax
0x7ffff7daa3bc <__run_exit_handlers+44>: mov edx,0x1
0x7ffff7daa3c1 <__run_exit_handlers+49>: lock cmpxchg DWORD PTR [r14],edx
0x7ffff7daa3c6 <__run_exit_handlers+54>: jne 0x7ffff7daa5ce <__run_exit_handlers+574>
0x7ffff7daa3cc <__run_exit_handlers+60>: xor ebx,ebx
(Profit)
0x7ffff7daa3ce <__run_exit_handlers+62> mov r15, QWORD PTR [r12]
0x7ffff7daa3d2 <__run_exit_handlers+66>: test r15,r15
0x7ffff7daa3d5 <__run_exit_handlers+69>: je 0x7ffff7daa510 <__run_exit_handlers+384>
0x7ffff7daa3db <__run_exit_handlers+75>: nop DWORD PTR [rax+rax*1+0x0]
(r15+0x8 might be 0x1)
0x7ffff7daa3e0 <__run_exit_handlers+80>: mov rax,QWORD PTR [r15+0x8]
0x7ffff7daa3e4 <__run_exit_handlers+84>: test rax,rax
(Then, the next jump does not should fulfilled)
0x7ffff7daa3e7 <__run_exit_handlers+87>: je 0x7ffff7daa500 <__run_exit_handlers+368>
0x7ffff7daa3ed <__run_exit_handlers+93>: sub rax,0x1
0x7ffff7daa3f1 <__run_exit_handlers+97>: mov rdx,rax
0x7ffff7daa3f4 <__run_exit_handlers+100>: mov QWORD PTR [r15+0x8],rax
0x7ffff7daa3f8 <__run_exit_handlers+104>: shl rdx,0x5
(r15+0x10 might be 0x4)
0x7ffff7daa3fc <__run_exit_handlers+108>: mov rcx,QWORD PTR [r15+rdx*1+0x10]
0x7ffff7daa401 <__run_exit_handlers+113>: cmp rcx,0x3
0x7ffff7daa405 <__run_exit_handlers+117>: je 0x7ffff7daa4b8 <__run_exit_handlers+296>
(Then, the next jump must fulfilled)
0x7ffff7daa40b <__run_exit_handlers+123>: cmp rcx,0x4
0x7ffff7daa40f <__run_exit_handlers+127>: je 0x7ffff7daa460 <__run_exit_handlers+208>
0x7ffff7daa460 <__run_exit_handlers+208>: add rdx,r15
(r15+0x18 might be initial + 0x18 (own value))
(r15+0x20 might be a pointer to string /bin/sh)
0x7ffff7daa463 <__run_exit_handlers+211>: mov rax,QWORD PTR [rdx+0x18]
0x7ffff7daa467 <__run_exit_handlers+215>: mov r13,QWORD PTR [rdx+0x20]
0x7ffff7daa46b <__run_exit_handlers+219>: mov QWORD PTR [rdx+0x10],0x0
0x7ffff7daa473 <__run_exit_handlers+227>: mov edx,ebx
A point: The struct initial is filled at start, it does not touched after main function.
(There is to know the initial struct with a possible leak, and get fs:0x30 calculating)
function = 0x00007ffff7fc9040 → <_dl_fini+0> endbr64
((initial + 0x18) >> 0x11) ^ function = fs:0x30
(After, overwrite initial + 0x18 with a own value for profit)
(system ^ fs:0x30) << 0x11 = initial + 0x18
0x7ffff7daa475 <__run_exit_handlers+229>: ror rax,0x11
0x7ffff7daa479 <__run_exit_handlers+233>: xor rax,QWORD PTR fs:0x30
0x7ffff7daa482 <__run_exit_handlers+242>: xchg DWORD PTR [r14],edx
0x7ffff7daa485 <__run_exit_handlers+245>: cmp edx,0x1
0x7ffff7daa488 <__run_exit_handlers+248>: jg 0x7ffff7daa5a0 <__run_exit_handlers+528>
0x7ffff7daa48e <__run_exit_handlers+254>: mov esi,ebp
0x7ffff7daa490 <__run_exit_handlers+256>: mov rdi,r13
0x7ffff7daa493 <__run_exit_handlers+259>: call rax
$r12 : 0x00007ffff7f7e838 → 0x00007ffff7f7ff00 → 0x0000000000000000
$r15 : 0x00007ffff7f7ff00 → 0x0000000000000000
0x00007ffff7f7e000 0x00007ffff7f80000 0x0000000000218000 rw- /usr/lib/x86_64-linux-gnu/libc.so.6
gef➤ x/20xg 0x00007ffff7f7e838
0x7ffff7f7e838 <__exit_funcs>: 0x00007ffff7f7ff00 0x00007ffff7f80320
gef➤ x/20xg 0x00007ffff7f7ff00
0x7ffff7f7ff00 <initial>: 0x0000000000000000 0x0000000000000000
0x7ffff7f7ff10 <initial+16>: 0x0000000000000000 0xc67fc1eb35a6fd2f
With a use-after-free we can write __exit_funcs to build a fake initial struct and get the call to system knowing what there is at fs:0x30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment