Hello guys this is a write-up for the two "hello world" PWN challenges from SquareCTF 2020.
Let's start, you can find the challenges and the exploits here in my GitHub:
[+] My GitHub
If you're just interested only by the second challenge scroll down a little bit.
Jimi - Jam (The first one)
This challenge was ret2libc challenge after getting the libc leak.
The main() function is easy as intended :
init_jail function just gives us a binary leak :
It sets srand() to a fixed value which means rand() return always expected values.
and it sets the page readable executable nothing so special here.
Vuln() function interest me more because we have a clear stack overflow!
I'm gonna use pop rdi gadget :
Let's run the binary :
My exploit for this challenge :
Here I'm just capturing the free binary leak and calculate the binary base address :
Here I'm storing addresses I want to use later :
This is the first ROP I'm going to send, it just sets rdi to
read@got and call
exe.plt['puts'] to leak that value, and at the end return to
main to give me another chance to ROP, nothing hard :
Here I'm just capturing the address of read and calculate Libc base address :
Now we know the address of system and /bin/sh in the GlibC, so I'm sending the next and final ROP, the extra ret there is just to align the stack :
Enjoy !
Jimmie_Jamming (second pwnie)
This time things a little bit different, we have the same main() as you can see :
some checks were added to init_jail() and vuln()
Let's start by init_jail():
srand() again to a fixed value, and then malloc(0x1000) and it stores the chunk address in ROPJAIL, then it fills the chunk with gibberish data from rand() and after each time i (the counter) ends with 0 like 0x10, 0x20, 0x30 ... it stores 0xc3 there which means ret.
Be careful that they may be some interesting gadgets in this gibberish by luck.
Now it asks you for a key this is actually a shellcode of size 10, because the chunk gets executable by mprotect() at the end, 10 bytes isn't enough to pop a shell but you need to combine this feature with other bugs.
Let's take a look at vuln.
Clear stack overflow but this time our input is checked.
This check just take the first 7 pointers from our payload (1 pointer is 8 bytes) and it should be smaller than 0x200000000 or somewhere in the range of the chunk of size 0x1000 we already know.
Be careful that just we have the check in the first 7 pointers, we're free to enter any data we want after the seventh one.
I started with running the binary and looking for good gadgets in the chunk.
I repeated this over and over again until I extracted some good gadgets for example :
I will be using this gadget to set
RAX to 0x3b ! syscall to execve()
My exploit for the challenge :
Because we can write up to 10 bytes of shellcode and we have a rop chain and even the place where we have the shellcode this challenge was hella easy, so all I'm doing here is setting RAX to 0x3B and jump to my shellcode to set other registers needed and syscall!
Here I'm writing my shellcode and I'm sending it :
We will see what the shellcode is doing.
Here I'm capturing the leak we got which is a heap address where our shellcode resides (executable heap) :
Pop Rax gadget and shellcode :
I'm gonna be using LEAK as padding to ROP because it satisfy the requirement being in the start of the chunk, it's good as padding to the return pointer.
Now let's send this rop and break in vuln() ret :
It will execute pop rax now let's take a look at the stack.
Let's go one instruction and see what RAX have :
Now we're inside the shellcode :
Let's see the stack one more time :
Perfect we're executing pop rdx, pop rsi so both of them become 0x0
Now we push rsp just to get a pointer to /bin/sh :
Now all we have to do is pop rdi and syscall :)
This comment has been removed by the author.
ReplyDeletelovely, your WUs are so clear, many thankssssssssssssss <3
DeleteThanks for your feedback, if you enjoy this write-up you can look for the 13 ones left.
Deleteyou find gadget by debugging it? can we dump it out in some ways?
ReplyDeleteI didn't found a way to extract gadgets without debugging. If you know other way please tell me :)
Delete