by @defund, @hgarrereyn and @Aplet123
binop
pops two, pushes value
binop c
pushes c
, calls binop
load
pops top (address on top), pushes value
store
pops two (address on top), address on top
jlt
pops two (greater on top)
nz
pops one
dup
replicates top of stack
pick
replicates element below top of stack
0x00: uint32_t ip
0x04: char unk (used as a temp var in f39)
0x05: char shuffle_offset (initialized to 1)
0x06: char ctr (used to track newlines)
0x07: char unk (initialized to 0)
0x08: char[0x20] buffer (used by f6)
0x28: char unk28
0x29: fd
0x2d: char[0x100] buffer... (used by f39)
0x12d: request_key
0x12e: char cidx (used in f34)
0x12f: unk
0x130: return value of connect() in f5
f0_start: 16, 25, 11, 10, 1, 25, 2
base[0x29] = accept()
base[0] = ?
f16_check_req_path() ; "GET /gather_everyone_to_reveal_our_secret"
f25_cmp_0()
f25_cmp_0()
f11_wait_for_newlines(base[0x29])
f10_is_local()
and
dup
if nz:
f1_good_req()
f25_cmp_0()
if nz:
f2_bad_req()
f1_good_req: 19, 26, 8, 9, 5, 3
f19_ok() ; "HTTP/1.0 200 OK\r\n\r\n"
f26_init_things() ; initialize some variables
f8_format_ip()
ip = f9()
f5_talk_to_peer(ip)
drop
ip = f9()
f5_talk_to_peer(ip)
drop
f3()
close(base[0x29])
finish()
f2_bad_req: 18
f18_bad()
close(base[0x29])
f3: 4
push 0
f4()
drop
f4(v): 29
dup ; v v
load base[8 + (pop)] ; v base[8+v]
f29()
xor
write(base[0x29])
add 1
dup
push 0x20
lt
jnz
f5_talk_to_peer(ip):
; ------------
; target_fd @ 0x130
; ------------
if [base+0x12d] == 0: return
target_fd = connect(ip, 8000)
if target_fd < 0: return
f17_make_request()
f11_wait_for_newlines(target_fd)
f6_read_body()
close(target_fd)
_old_f5: 24, 17, 11, 6
push base
push 0x12d
add
load
push 0
if !eq: ;
dup ; ip ip
push 0x1f40 ; ip ip 8000
connect(8000, ip)
push base
push 0x130
add
set
; base[0x130] = connect(ip, 8000)
push base
push 0x130
add
load
f24_is_negative()
if eqz: <= 0x7fffffff
; make a request to another server
f17_make_request()
push base
push 0x130
add
load
f11_wait_for_newlines()
f6_read_body()
push base
push 0x130
add
load
close()
f6_read_body: 7
; reads 32 bytes from socket, xors with base[8], base[9], ..., base[8+32]
push 0
f7()
pop
f7(a):
dup ; [a, a]
push base ; [base, a, a]
add 8 ; [base+8, a, a]
add ; [base+8+a, a]
dup
load ; [v, base+8+a, a]
load base[0x130] ; [fd, v, base+8+a, a]
read() ; [char, v, base+8+a, a]
xor ; [char^v, base+8+a, a]
swap ; [base+8+a, char^v, a]
store ; [a]
add 1 ; [a+1]
dup ; [a+1, a+1]
push 0x20 ; [0x20, a+1, a+1]
jlt ; [a+1]
f8_format_ip: 27
load base[0] ; ip
dup ; ip ip
and 0xff ; ip ip[0]
swap ; ip[0] ip
shr 8 ; ip[0] (ip>>8)
dup ; ip[0] (ip>>8) (ip>>8)
and 0xff ; ip[0] (ip>>8) ip[1]
swap ; ip[0] ip[1] (ip>>8)
shr 8 ; ip[0] ip[1] (ip>>16)
dup
and 0xff
swap
shr 8 ; ip[0] ip[1] ip[2] ip[3]
f27()
f27()
f27()
f27()
f9: 29
push 0xa00
f29()
add
push 0x100
mul
f29()
add
push 0x100
mul
f29()
add
f10_is_local:
ret (base[0] >> 0x18) == 10
f11_wait_for_newlines(fd): 14, 12
f14_reset_ctr()
f12_inner_wait_for_newlines(fd)
drop
; this function waits for a newline followed by a return
f12_inner_wait_for_newlines(fd): 13, 25, 14, 24, 15
dup ; fd is on top of stack
read
dup
dup
push 10 ; '\n'
eq
dup
if nz: f13_inc_ctr()
f25_cmp_0()
swap
push 0xd ; '\r'
eq
f25_cmp_0()
and
if nz: f14_reset_ctr()
f24()
if nz: f15_ctr_set_2()
load base[6]
push 2
jlt
base[6] seems to act as some sort of counter?
f13_inc_ctr:
base[6] += 1
f14_reset_ctr:
base[6] = 0
f15_ctr_set_2:
base[6] = 2
f16_check_req_path: 25
read match "GET /gather_everyone_to_reveal_our_secret"
read(base[0x29])
dup ; v v
push 0x20 ; ' '
ensure eq ; v
push 0
swap ; not sure here ; 0 v
push '?'
xor
ensure eq ; 0 = v^?
read(base[0x29])
push 0x30
sub
push base
push 0x12d
add
store
; [base+0x12d] = read(fd) - 0x30
read(base[0x29])
push 0x20 ; ' '
xor
ensure eqz
push 2
push base
push 0x12d
add
load
if gt: ; this condition might be inverted
f25_cmp_0()
f17_make_request:
write "GET /gather_everyone_to_reveal_our_secret?"
push 0x30
push base
push 0x12d
add
load
add ; [base+0x12d]+0x30
push 1
sub ; [base+0x12d]+0x30-1
push base
push 0x130
add
load
write
write " HTTP/1.0\r\n\r\n"
f18_bad:
push "HTTP/1.0 403 Forbidden\r\n\r\n"
load base[0x29]
write
f19_ok:
push "HTTP/1.0 200 OK\r\n\r\n"
load base[0x29]
write
f20_init_buffer(buffer, len): 21
; initializes buffer to [0, 1, 2, ..., 254, 255]
pick ; [len, fd, len]
add ; [fd+len, len]
sub 1 ; [fd+len-1, len]
swap ; [len, fd+len-1]
f21()
pop
pop
f21(len, addr):
sub 1 ; [len-1, addr]
swap ; [addr, len-1]
pick ; [len-1, addr, len-1]
pick ; [addr, len-1, addr, len-1]
store ; [addr, len-1]
sub 1 ; [addr-1, len-1]
swap ; [len-1, addr-1]
dup ; [len-1, len-1, addr-1]
jnz ; [len-1, addr-1]
; returns 0, b-a
; unused
f22(addr, len): 23
pick ; [len, addr, len]
add ; [addr+len, len]
sub 1 ; [addr+len-1, len]
swap ; [len, addr+len-1]
f23()
pop
pop
; unused
f23(len, addr):
sub 1 ; [len-1, addr]
swap ; [addr, len-1]
pick ; [len-1, addr, len-1]
pick ; [addr, len-1, addr, len-1]
load ; [v, len-1, addr, len-1]
debug ; [v, len-1, addr, len-1] prints v
pop ; [len-1, addr, len-1]
pop ; [addr, len-1]
sub 1 ; [addr-1, len-1]
swap ; [len-1, addr-1]
dup ; [len-1, len-1, addr-1]
jnz ; [len-1, addr-1]
; returns 0, addr-l
f24_is_negative(x):
push 0x7fffffff
swap
lt
; returns whether x > 0x7fffffff
f25_cmp_0(x):
push 0
eq
; returns whether x is zero
f26_init_things: 20
base[0x12e] = 0
base[0x28] = 0
base[0x134] = 0
base[0x12f] = 0
base[7] = 0
base[5] = 1
f20_init_buffer(base[0x2d], 0x100)
f27(char v):
f28(v & 0xf)
f28(v >> 4)
f28(char v): 31, 39 ; takes a nibble
if base[7] == 0x80:
f31_shuffle_sort()
add 0x80
f39_swap_idx(base[7])
base[7] += 1
f29: 31, 34, 30
load base[7]
if nz:
f31_shuffle_sort()
f34_inner_shuffle()
f30_update_shuffle_keys()
; related to shuffling
f30_update_shuffle_keys():
; -------------
; cidx @ 0x12e
; -------------
v = ([base+0x134] + [base+0x12f]) & 0xff
v2 = (buffer[v] + [base+cidx]) & 0xff
v3 = (buffer[v2] + [base+28]) & 0xff
[base+0x12f] = buffer[v3]
_old_f30():
load base[0x134]
load base[0x12f]
add
and 0xff
load base[0x2d + (pop)]
load base[0x12e]
add
and 0xff
load base[0x2d + (pop)]
load base[0x28]
add
and 0xff
load base[0x2d + (pop)]
dup
store base[0x12f]
; returns the stored value
f31_shuffle_sort: 32, 35
f32_outer_shuffle(0x200)
f35_sort()
f32_outer_shuffle(0x200)
f35_sort()
f32_outer_shuffle(0x200)
base[7] = 0
f32_outer_shuffle(n): 33
; -------------
; shuffle_offset @ 0x5
; -------------
f33_shuffle(n)
pop
shuffle_offset += 2
; perform inner shuffle N times
f33_shuffle(n): 34
f34_inner_shuffle()
sub 1
dup
jnz
; seems like an inner shuffle thing
f34_inner_shuffle:
; -------------
; shuffle_offset @ 0x5
; unk28 @ 0x28
; cidx @ 0x12e
; -------------
cidx += shuffle_offset
v = (buffer[cidx] + unk28) & 0xff
unk28 = buffer[v] + [base+0x134]
[base+0x134] = buffer[unk28] + [base+0x134] + [base+cidx]
swap_idx(unk28, cidx)
_old_f34: 39
load base[0x12e] ; base[0x12e]
load base[5] ;
add ; (base[0x12e]+base[0x5])
store base[0x12e]
; [base+0x12e] += [base+0x5]
load base[0x12e]
load base[0x2d + (pop)] ; [base+0x2d+[base+0x12e]]
load base[0x28]
add
and 0xff
; ([base+0x2d+[base+0x12e]]+base[0x28]) & 0xff
load base[0x2d + (pop)] ; [base+0x2d+v]
load base[0x134]
add
store base[0x28]
load base[0x28]
load base[0x2d + (pop)]
load base[0x134]
add
load base[0x12e]
add
store base[0x134]
load base[0x12e]
load base[0x28]
f39_swap_idx()
; sorts the first 0x80 elements of the buffer at 0x2d
f35_sort: 36
f36_inner_sort(0x80)
pop
f36_inner_sort(v): 37
push 1 ; v 1
sub ; v-1
f37()
dup
jnz
f37(v): 38
dup ; v v
load base[0x2d + (pop)] ; v [base+0x2d+v]
pick ; v [base+0x2d+v] v
push 0xff ; v [base+0x2d+v] v 0xff
swap ; v [base+0x2d+v] 0xff v
sub ; v [base+0x2d+v] (0xff-v)
load base[0x2d + (pop)] ; v [base+0x2d+v] [base+0x2d+0xff-v]
swap ; v [base+0x2d+0xff-v] [base+0x2d+v]
lt
if nz: f38(v)
f38(v): 39
dup ; v v
dup ; v v v
push 0xff ; v v v 0xff
swap ; v v 0xff v
sub ; v v (0xff-v)
f39_swap_idx(0xff-v)
f39_swap_idx(v):
[base+4] = [base+0x2d+v]
[base+0x2d+v] = [base+0x2d]
[base+0x2d] = [base+4]
_asm_f39(v):
push base ; v base
add 0x2d
add ; v (base+0x2d)
swap ; (base+0x2d) v
push base
add 0x2d
add ; (base+0x2d) (base+0x2d+v)
dup ; (base+0x2d) (base+0x2d+v) (base+0x2d+v)
load ; (base+0x2d) (base+0x2d+v) [base+0x2d+v]
push base
add 4 ; (base+0x2d) (base+0x2d+v) [base+0x2d+v] (base+4)
store ; (base+0x2d) (base+0x2d+v)
; [base+4] = [base+0x2d+v]
pick ; (base+0x2d) (base+0x2d+v) (base+0x2d)
load ; (base+0x2d) (base+0x2d+v) [base+0x2d]
swap ; (base+0x2d) [base+0x2d] (base+0x2d+v)
store ; (base+0x2d)
; [base+0x2d+v] = [base+0x2d]
load base[4] ; (base+0x2d) [base+4]
swap ; [base+4] = (base+0x2d)
store
; [base+0x2d] = [base+4]