3x17 — pwnable.tw
###gathering
because the binary was statistically linked, all of the function will be harder to reversing
main
- creating buf at rbp -0x20
sub_40EE70
when I first jump in and back out again it’s only passing 1 arg
inside it was something i won’t talk about cause it’s too much for me xD
sub_44A3E0
the same as sub_40EE70. the main changed entirely
and inside sub_413260 getting more weirder
— — — — — — — — — — — — — — — — — — — — —
now let’s sum up, what do we have?
- it seems like the binary let us write data to a specific function
- the author messed up the binary so that we can’t reverse ourself
so we can only write something to a specific addrs, what do we write? to continue this challenge we need to understand about the .init_array
and .fini_array
section, i’ll use the 2 site that’s give me more infomation about those
- https://github.com/smokeleeteveryday/CTF_WRITEUPS/tree/master/2016/CODEGATE/pwnable/oldschool
- http://blog.k3170makan.com/2018/10/introduction-to-elf-format-part-v.html
As we can see
.fini_array
holds the address of a destructor function which will be executed when the application terminates. So if we use our fms to overwrite the.fini_array
entry with an address of our choice we can hijack EIP control upon application termination.
Digging around the internets, i found this
According to Chapter 11 of Linux Standard Base Core Specification 3.1
.fini_array
This section holds an array of function pointers that contributes to a single termination array for the executable or shared object containing the section.
basically, the .fini_array
use to terminate our program when it’s utilities to the user was finished.
let’s find the address of .fini_array
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
int argc, char **argv,
#ifdef LIBC_START_MAIN_AUXVEC_ARG
ElfW(auxv_t) *auxvec,
#endif
__typeof (main) init,
void (*fini) (void),
void (*rtld_fini) (void), void *stack_end)
base on the snippet above, we found our entry
sub_401B6D
was our main function, and that’s mean sub_401EB0
was __libc_start_main
. so the .fini_array
was sub_402960
.
so what if we write our main function to it? we will have a infinite loop of main to write any we want to it. So in this challenge we using ROP to get our way out!
###exploitation
because our binary was x64 bit so our rop gadgets gonna different from the x32. regs state to gain shell
- rax == 59d (0x3b)
- rdi == point to /bin/sh
- rsi == NULL
- rdx == NULL
gadgets
0x000000000041e4af : pop rax ; ret
0x0000000000401696 : pop rdi ; ret
0x0000000000446e35 : pop rdx ; ret
0x0000000000406c30 : pop rsi ; ret
0x00000000004022b4 : syscall
setting up our gadgets
we gonna send 16 bytes to data (reduce the ugliness for our script)
now before we actually finish, do you remember that you write our .fini_array
became main? like I said, the program keeps looping infinitely or you have to interupt. So you need a gadgets that’s can help us break the loop.
0x0000000000401c4b : leave ; ret
put this at the start of the .fini_array
then we’re good to go
this wu was create tks to drx wu!!!