silver bullet — pwnable.tw

###gathering

main()
menu()
read_int()
power_up(&s)
create_bullet(&s)
read_input(s, 30)
beat((int)&s, &hp)

the binary ask user to input a bullet that can kill off the werewolf, let step through the pseudo code

check if *s !=\0, then call the read_input function, as the name of the function, it read input from user, null the ‘\n’ character. Finished the read_input, store the length of v2 at *s + 12

now we need to power up our bullet to shoot the werewolf, but the binary restrict only 48 byte input and stop us from powerup (the binary use the length_s to check)

if our description isn’t filled up 0x30 bytes, it increase our value acording to our input, and v3 = len(&s) (our 2nd input description) + previous length description, then return v3.

in normal ways, if you filled up 48 bytes, then it’s done, nothing more. But we’re pwner, if you’ve already read the pseudo-code atm, you’ll notice something suspicious. the strncat, there’s a off-byte-one bug to it. Because the strncat append the next string to the buffer, and end with a null byte.

now because the new power have been reset we can overwrite the next buffer of s

now we can write anything we want !!!

sum up:

  • create bullet with 47bytes
  • powerup 1 bytes (leads to off-byte-one)
  • powerup again (padding)
  • call beat

###exploit

because our binary have NX-on, we have to use ret2libc to gain shell, but first we need to leak the libc address because the remote server always turn on ASLR. in order to leak the libc base, we need to replace the ret addr with puts@plt and pass to it any got symbol you like (ex: puts.got), and the ret of puts is main

now we have the libc base, we can call system(‘/bin/sh\x00’) to gain our shell!!!

happy hacking!!!

a loner