3x17 — pwnable.tw

Nguyễn Tín
4 min readMay 3, 2020



because the binary was statistically linked, all of the function will be harder to reversing


  • creating buf at rbp -0x20


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


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

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

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,
ElfW(auxv_t) *auxvec,
__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!


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


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!!!