dora

Swiper, no swiping!

2 min read


Table of Contents

[ + ] Overview
[ + ] Reversing
[ + ] Solution

[ + ]Overview

Playing around with the binary we are prompted for a key, and if that key is wrong, we get a segfault.

Image

Lets take a deeper look.

[ + ]Reversing

From a high-level, and looking at the psuedo code, this challenge looks fairly innocuous. It is not until you look at the instructions themselves that you get the full picture.

Image

It seems like some number is read, then something is XOR'd, then a call is made. In IDA, this pseudo code is symptomatic of weird calls being make.

Taking a look at the assembly, the idea behind this challenge is that the bytes at a memory address are XOR'd by the value provided, then the memory location is called using call rdx (highlighted in red). To solve, you need to find the right value to be able to have working code at that memory location when call rdx happens.

Image

[ + ]Solution

My solution was kind of un-orthodox, but worked. I figured there is no reference to any other memory addresses, flag.txt , or imports, so the values being XOR'd must actually open and read the flag.txt file. By that logic, I simply brute forced it:

def solve():
    ida_chars = bytes([
        0x97, 0x46, 0x23, 0x34, 0x4D, 0x8A, 0xC4, 0x7E, 0x7C, 0x7C,
        0x7C, 0x73, 0x79, 0x97, 0x47, 0x22, 0x34, 0xF5, 0xBB, 0xC6,
        0x83, 0x7C, 0x7C, 0x7C, 0xC4, 0x7C, 0x7C, 0x7C, 0x7C, 0x73,
        0x79, 0xC3, 0x7D, 0x7C, 0x7C, 0x7C, 0xC6, 0x83, 0x7C, 0x7C,
        0x7C, 0xC4, 0x7D, 0x7C, 0x7C, 0x7C, 0x73, 0x79, 0xC3, 0x7C,
        0x7C, 0x7C, 0x7C, 0xC4, 0x40, 0x7C, 0x7C, 0x7C, 0x73, 0x79,
        0x94, 0xBD, 0x83, 0x83, 0x83, 0x1A, 0x10, 0x1D, 0x1B, 0x52,
        0x08, 0x04, 0x08, 0x7C, 0x94, 0xBC
    ])
    for i in range(256):
        flag = bytes(x ^ i for x in ida_chars)
        if b"flag" in flag:
            print(i)
            return i
    return -1

I was able to verify that this is correct by debugging after the XOR:

Image

As shown, there are syscalls happening to open and read flag.txt .

Image
 Solver
import sys
from pwn import *
from pwnlib.util.packing import *
# Context
context.arch = 'amd64'
context.log_level = 'DEBUG'
# Main vars
NETID = ''
HOST, PORT = 'host', 1250
def solve():
    ida_chars = bytes([
        0x97, 0x46, 0x23, 0x34, 0x4D, 0x8A, 0xC4, 0x7E, 0x7C, 0x7C,
        0x7C, 0x73, 0x79, 0x97, 0x47, 0x22, 0x34, 0xF5, 0xBB, 0xC6,
        0x83, 0x7C, 0x7C, 0x7C, 0xC4, 0x7C, 0x7C, 0x7C, 0x7C, 0x73,
        0x79, 0xC3, 0x7D, 0x7C, 0x7C, 0x7C, 0xC6, 0x83, 0x7C, 0x7C,
        0x7C, 0xC4, 0x7D, 0x7C, 0x7C, 0x7C, 0x73, 0x79, 0xC3, 0x7C,
        0x7C, 0x7C, 0x7C, 0xC4, 0x40, 0x7C, 0x7C, 0x7C, 0x73, 0x79,
        0x94, 0xBD, 0x83, 0x83, 0x83, 0x1A, 0x10, 0x1D, 0x1B, 0x52,
        0x08, 0x04, 0x08, 0x7C, 0x94, 0xBC
    ])
    for i in range(256):
        flag = bytes(x ^ i for x in ida_chars)
        if b"flag" in flag:
            print(i)
            return i
    return -1
    
def pwn():
    conn = remote(HOST, PORT)
    conn.recvuntil(b'(something like abc123): ')
    conn.sendline(NETID)
    conn.recvuntil(b'What\'s the key?')
    sol = solve()
    if sol == -1:
        print("No solution found")
        sys.exit(1)
    conn.sendline(f"{sol}")
    conn.recvuntil(b'flag{')
    response = conn.recvline()
    conn.close()
    print("flag{" + response.decode().strip())
    
if __name__ == "__main__":
    pwn()