# RARPG```I've been building a brand new Massively(?) Multiplayer(?) Online Role-Playing(?) Game(?) - try it out! Just don't try and visit the secret dev room...
If you do not have the linked libraries, download rarpg-libs.zip and extract the libraries into your working directory. Then useLD_LIBRARY_PATH=$(pwd) ./client <ip> <port>```
- File : [client](https://github.com/Pynard/writeups/blob/main/2021/RARCTF/attachements/rarpg/client)
## Client AnalysisHere we have a client for an ascii game\The goal is to get to the "dev zone"
Looking at the game we have 3 types of tile :
- walkable- teleporter (X)- wall (~ or W)```┌────────────────────────────────────────────────────────────────────────────────────────────────────────────┐│                X                                                                                           ││                                                                                                            ││         ~~~~~~~~~~~~~~~      WWWWWW                                                                        ││X        ~~~~~~~~~~~~~~~      W   XW                                                                        ││         ~~~~~~~~~~~~~~~      WWWWWW                                                                        ││     *                                                                                                      ││                X                                                                                           ││                                                                                                            │```You are the **\***
Being through all teleporters it seems that we are interested by the one enclosed by **W**
Looking at the client, there is an interesting function **sym.move_okay_int\_\_int\_**```┌ 116: sym.move_okay_int__int_ (int64_t arg1, int64_t arg2);│           ; var int64_t var_11h @ rbp-0x11│           ; var int64_t var_10h @ rbp-0x10│           ; var uint32_t var_ch @ rbp-0xc│           ; var int64_t var_8h @ rbp-0x8│           ; var int64_t var_4h @ rbp-0x4│           ; arg int64_t arg1 @ rdi│           ; arg int64_t arg2 @ rsi│           0x00404970      55             push rbp                    ; move_okay(int, int)│           0x00404971      4889e5         mov rbp, rsp[...]│           0x004049ba      8945f4         mov dword [var_ch], eax│           0x004049bd      837df420       cmp dword [var_ch], 0x20│           0x004049c1      b101           mov cl, 1│           0x004049c3      884def         mov byte [var_11h], cl│       ┌─< 0x004049c6      0f840a000000   je 0x4049d6│       │   0x004049cc      837df458       cmp dword [var_ch], 0x58│       │   0x004049d0      0f94c0         sete al│       │   0x004049d3      8845ef         mov byte [var_11h], al│       │   ; CODE XREF from move_okay(int, int) @ 0x4049c6│       └─> 0x004049d6      8a45ef         mov al, byte [var_11h]│           0x004049d9      2401           and al, 1│           0x004049db      0fb6c0         movzx eax, al│           0x004049de      4883c420       add rsp, 0x20│           0x004049e2      5d             pop rbp└           0x004049e3      c3             ret```
Here two **cmp** are important @ 0x004049bd and 0x004049ccThe first check if we want to move the player to an empty tile : **0x20 = ' '** \The second one check if we are going to a teleporter : **0x58 = 'X' **
## Communication analysisTo analyse communication between client and server, I have slightly modified a simple udp replay python script from [here](https://github.com/EtiennePerot/misc-scripts/blob/master/udp-relay.py) (Thx to EtiennePerot) :
- File : [udp-relay.py](https://github.com/Pynard/writeups/blob/main/2021/RARCTF/attachements/rarpg/udp-relay.py)```python#!/usr/bin/env python# Super simple script that listens to a local UDP port and relays all packets to an arbitrary remote host.# Packets that the host sends back will also be relayed to the local UDP client.# Works with Python 2 and 3
import sys, socketimport parserimport importlib
# Whether or not to print the IP address and port of each packet receiveddebug=False
def fail(reason):    sys.stderr.write(reason + '\n')    sys.exit(1)
if len(sys.argv) != 2 or len(sys.argv[1].split(':')) != 3:    fail('Usage: udp-relay.py localPort:remoteHost:remotePort')
localPort, remoteHost, remotePort = sys.argv[1].split(':')
try:    localPort = int(localPort)except:    fail('Invalid port number: ' + str(localPort))try:    remotePort = int(remotePort)except:    fail('Invalid port number: ' + str(remotePort))
try:    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    s.bind(('', localPort))except:    fail('Failed to bind on port ' + str(localPort))
knownClient = NoneknownServer = (remoteHost, remotePort)sys.stdout.write('All set, listening on '+str(localPort)+'.\n')while True:    importlib.reload(parser)    data, addr = s.recvfrom(32768)    if knownClient is None or addr != knownServer:        if debug:            print("")        knownClient = addr
    if debug:        print("Packet received from "+str(addr))
    if addr == knownClient:        if debug:            print("\tforwording tO "+str(knownServer)) 
        s.sendto(parser.parse(data,True), knownServer)    else:        if debug:            print("\tforwarding to "+str(knownClient))        s.sendto(parser.parse(data,False), knownClient)```
And a parser dynamically imported to manipulate packets.\Thanks to this we can see that packets with the map are sent from the server to the client.
So one way to solve this challenge is to manipulate the map for the player to be able to walk to the "dev teleporter"The parser is very simple :
- File : [parser.py](https://github.com/Pynard/writeups/blob/main/2021/RARCTF/attachements/rarpg/parser.py)```pythonimport binascii
def parse(data,out):    if len(data) != 198:        return data
    if out:        print('--> ',end='')    else:        print('<-- ',end='')
    data = data.replace(b'W',b' ')    print(data)
    return data```
Now the teleporter is free to walk on :```┌────────────────────────────────────────────────────────────────────────────────────────────────────────────┐│                X                                                                                           ││                                                                                                            ││         ~~~~~~~~~~~~~~~                                                                                    ││X        ~~~~~~~~~~~~~~~          X                                                                         ││         ~~~~~~~~~~~~~~~                                                                                    ││           *                                                                                                ││                X                                                                                           ││                                                                                                            │```
and we get the flag :```┌────────────────────────────────────────────────────────────────────────────────────────────────────────────┐│*                                                                                                           ││    rarctf{g4m3_h4ck1ng_f0r_n00b5!-75f8b0}                                                                  ││                                                                                                            ││                                                                                                            │```
flag : `rarctf{g4m3_h4ck1ng_f0r_n00b5!-75f8b0}`