1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SunshainCTF 2025 - Re Writeup

Posted at

SunshineCTF 2025

  • Sat, 27 Sept. 2025, 14:00 UTC — Mon, 29 Sept. 2025, 14:00 UT

BASEic

  • 10pt
  • created by Tyler (brosu)
  • provided file : BASEic

Question

The space base is in danger and we lost the key to get in!
$ file BASEic                                                                                                                                 ❮❮❮
BASEic: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4c27a8522e5cde996407511f18c475d48dda4ea9, for GNU/Linux 3.2.0, stripped

実行形式ファイルであることが分かった
stringsで文字列を調べる

$ strings BASEic                                                                                                                              ❮❮❮
/lib64/ld-linux-x86-64.so.2
__cxa_finalize
malloc
__libc_start_main
strncmp
puts
free
strlen
__isoc99_scanf
__stack_chk_fail
printf
libc.so.6
GLIBC_2.7
GLIBC_2.4
GLIBC_2.34
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
yX0I0NTMH
1fQ=f
c3Vue2MwdjNyMW5nX3V
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
What is the flag>
%40s
You got it, submit the flag!
Soo Close
Closer
You don't get the flag that easily
:*3$"
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment

You got it, submit the flag! がflagを取得した時に表示されるメッセージっぽい

Ghidraでデコンパイルする
GhidraのDefinded StringsYou got it, submit the flag!を検索する

image.png

あった
FUN_001014d1で実行されているようなので、Symbol TreeのFunctionsからその関数を探す

image.png

デコンパイルの結果が以下

undefined8 FUN_001014d1(void)

{
  int iVar1;
  size_t sVar2;
  char *__s1;
  long in_FS_OFFSET;
  char local_56 [70];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  builtin_strncpy(local_56,"yX0I0NTM1fQ==",0xe);
  printf("What is the flag> ");
  __isoc99_scanf(&DAT_00102094,local_56 + 0xe);
  sVar2 = strlen(local_56 + 0xe);
  if (sVar2 == 0x16) {
    sVar2 = strlen(local_56 + 0xe);
    __s1 = (char *)FUN_001012c6(local_56 + 0xe,sVar2);
    iVar1 = strncmp(__s1,"c3Vue2MwdjNyMW5nX3V",0x13);
    if (iVar1 == 0) {
      sVar2 = strlen(local_56);
      iVar1 = strncmp(__s1 + 0x13,local_56,sVar2);
      if (iVar1 == 0) {
        puts("You got it, submit the flag!");
      }
      else {
        puts("Soo Close");
      }
    }
    else {
      puts("Closer");
    }
    free(__s1);
  }
  else {
    puts("You don\'t get the flag that easily");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}
Answer

おおよそbase64の分割された文字列のようなものが見えているので結合してデコードしてみるとフラグが得られた

c3Vue2MwdjNyMW5nX3VyX0I0NTM1fQ==

flag は sun{c0v3r1ng_ur_B4535}


Missoncritical1

  • 10pt
  • provided chall

Question

Ground Control to Space Cadet!

We've intercepted a satellite control program but can't crack the authentication sequence. The satellite is in an optimal transmission window and ready to accept commands. Your mission: Reverse engineer the binary and find the secret command to gain access to the satellite systems.

fileの種類を調べる

# file chall
chall: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=643f888f6a846b88e61a61a180506277b41c610d, for GNU/Linux 4.4.0, stripped

x86の実行ファイル
実行してみる

root@2dbc224c45a8:/app# ./chall
Satellite Status: Battery=80%, Orbit=32, Temp=-25C
Enter satellite command: fjsoifncvnoas
Access Denied!

stringsで文字列検索

 strings chall                                                                                                           ❮❮❮
/lib64/ld-linux-x86-64.so.2
fgets
stdin
puts
__stack_chk_fail
time
__libc_start_main
__cxa_finalize
sprintf
strcmp
libc.so.6
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
D$x1
|$@H
D$xdH+
PTE1
u3UH
3131
s4t3ll1t3
e4sy
sun{%s_%s_%s}
Enter satellite command:
Access Granted!
Access Denied!
Satellite Status: Battery=%d%%, Orbit=%d, Temp=%dC
;*3$"
GCC: (GNU) 15.1.1 20250425
.shstrtab
.note.gnu.property
.note.gnu.build-id
.interp
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.note.ABI-tag
.init_array
.fini_array
.dynamic
.got
.got.plt
.data
.bss
.comment

Access Granted!が成功パターンのようなのでGhidraでデコンパイル

image.png

Ghidraで文字列検索すると、FUN_001010a0で動いている関数であることが分かった
Symbol Tree > Functions から該当の関数を見る

image.png

検証

デコンパイルしたソースは以下


undefined8 FUN_001010a0(void)

{
  int iVar1;
  long in_FS_OFFSET;
  char acStack_98 [64];
  char local_58 [56];
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  sprintf(acStack_98,"sun{%s_%s_%s}\n",&DAT_00102013,"s4t3ll1t3",&DAT_00102004);
  time((time_t *)0x0);
  printf("Satellite Status: Battery=%d%%, Orbit=%d, Temp=%dC\n",0x50,0x20,0xffffffe7);
  printf("Enter satellite command: ");
  fgets(local_58,0x32,stdin);
  iVar1 = strcmp(local_58,acStack_98);
  if (iVar1 == 0) {
    puts("Access Granted!");
  }
  else {
    puts("Access Denied!");
  }
  if (local_20 == *(long *)(in_FS_OFFSET + 0x28)) {
    return 0;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}


flagはsprintf(acStack_98,"sun{%s_%s_%s}\n",&DAT_00102013,"s4t3ll1t3",&DAT_00102004); で出力されている

&DAT_00102013Label.dataにあるかもしれない
SymbolTreeとProgram Treeから見ていく
なかった

デコンパイルした上記の文の引数をクリックしたら飛べた

image.png

00102013~0012017までがDAT_00102013の範囲で easy と表示されている

同じくDAT_00102004も上記にあるように 3131 であることが分かった

Answer

あとは条件に合うように sprintf(acStack_98,"sun{%s_%s_%s}\n",&DAT_00102013,"s4t3ll1t3",&DAT_00102004);を組み立てると
sprintf(acStack_98,"sun{%s_%s_%s}\n","easy","s4t3ll1t3","3131");

flag は sun{easy_s4t3ll1t3_3131}


RomanRomance

  • 10pt
  • created by Uvuv
  • provided files: enc.txt, romanromance

Question

When in Rome...

currently has nonstandard flag format sunshine{}

enc.txtを調べる

 cat enc.txt                                                                                                         ❮❮❮
tvotijof|lO1x`z1v5`s1nAo`iJ6u1sZ~

flagを何かしらエンコードした形っぽい
実行ファイルを調べる

 file romanromance                                                                                                           ❮❮❮
romanromance: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=22691467481039a1263756b806396768fd707772, for GNU/Linux 3.2.0, not stripped

x86の実行形式
実行してみる

root@5a8b0d987e31:/app# ./romanromance
Segmentation fault

すぐにSegmentation Faultを起こした

stringsで文字列検索する

 strings romanromance                                                                                                        ❮❮❮
/lib64/ld-linux-x86-64.so.2
__cxa_finalize
malloc
fseek
__libc_start_main
fopen
fclose
ftell
puts
free
stderr
fread
perror
rewind
fwrite
libc.so.6
GLIBC_2.34
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
flag.txt
malloc failed
fread
enc.txt
fwrite
[38;2;139;0;0m
/*************************************************************************************\
  MWAHAAHAHAH SAY GOOD-BYTE TO YOUR FLAG ROMAN FILTH!!!!! >:)
  OUR ENCRYPTION METHOD IS TOO STRONG TO BREAK. YOU HAVE TO PAY US >:D
  PAY 18.BTC TO THE ADDRESS 1BEER4MINERSMAKEITRAINCOINSHUNT123 TO GET YOUR FLAG BACK,
  OR WE SACK ROME AND I TAKE HONORIA'S HAND IN MARRIAGE! SIGNED, ATTILA THE HUN.
:*3$"
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Scrt1.o
__abi_tag
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.0
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
romanromance.c
__FRAME_END__
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
free@GLIBC_2.2.5
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
puts@GLIBC_2.2.5
fread@GLIBC_2.2.5
_edata
fclose@GLIBC_2.2.5
_fini
rewind@GLIBC_2.2.5
__data_start
ftell@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
malloc@GLIBC_2.2.5
_end
fseek@GLIBC_2.2.5
__bss_start
main
fopen@GLIBC_2.2.5
perror@GLIBC_2.2.5
fwrite@GLIBC_2.2.5
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@GLIBC_2.2.5
_init
stderr@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment

flag.txtという文字列があるのでそこにあたりをつけてみる
またmainもあるのでmain関数がおそらく存在する
Ghidraでデコンパイルする

image.png

flag.txtの文字列もあった
main関数を見てみる

検証


undefined8 main(void)

{
  FILE *pFVar1;
  size_t __size;
  void *__ptr;
  undefined8 uVar2;
  size_t sVar3;
  long local_30;
  
  pFVar1 = fopen("flag.txt","r+b");
  fseek(pFVar1,0,2);
  __size = ftell(pFVar1);
  rewind(pFVar1);
  __ptr = malloc(__size);
  if (__ptr == (void *)0x0) {
    fwrite("malloc failed\n",1,0xe,stderr);
    fclose(pFVar1);
    uVar2 = 1;
  }
  else {
    sVar3 = fread(__ptr,1,__size,pFVar1);
    if (sVar3 == __size) {
      for (local_30 = 0; local_30 < (long)__size; local_30 = local_30 + 1) {
        *(char *)((long)__ptr + local_30) = *(char *)((long)__ptr + local_30) + '\x01';
      }
      fclose(pFVar1);
      pFVar1 = fopen("enc.txt","w");
      sVar3 = fwrite(__ptr,1,__size,pFVar1);
      if (sVar3 == __size) {
        free(__ptr);
        fclose(pFVar1);
        puts(&DAT_00102040);
        puts(
            "/*************************************************************************************\ \ \n"
            );
        puts("  MWAHAAHAHAH SAY GOOD-BYTE TO YOUR FLAG ROMAN FILTH!!!!! >:) ");
        puts("  OUR ENCRYPTION METHOD IS TOO STRONG TO BREAK. YOU HAVE TO PAY US >:D ");
        puts(
            "  PAY 18.BTC TO THE ADDRESS 1BEER4MINERSMAKEITRAINCOINSHUNT123 TO GET YOUR FLAG BACK,  "
            );
        puts("  OR WE SACK ROME AND I TAKE HONORIA\'S HAND IN MARRIAGE! SIGNED, ATTILA THE HUN.  \n"
            );
        puts(
            "/*************************************************************************************\ \ \n"
            );
        uVar2 = 0;
      }
      else {
        perror("fwrite");
        free(__ptr);
        fclose(pFVar1);
        uVar2 = 1;
      }
    }
    else {
      perror("fread");
      free(__ptr);
      fclose(pFVar1);
      uVar2 = 1;
    }
  }
  return uVar2;
}

自力では理解ができなかった
GPTに聞いてみたら、以下が重要な処理ということが分かった

for (local_30 = 0; local_30 < (long)__size; local_30 = local_30 + 1) {
    *(char *)((long)__ptr + local_30) = *(char *)((long)__ptr + local_30) + '\x01';
}
  • local_30変数を繰り返し
    • local_30にはcharなので文字列が入っていることから文字列を1文字づつ繰り返し
  • 文字列の各文字を +1 して再起的に local_30に格納する
    • \x01 は16進数の1だが即値として扱われる

全体の処理としては以下

  • pFVar1 = fopen("flag.txt","r+b"); で flag.txt を読み取り権限で読み込む
  • __ptr = malloc(__size);で読み込んだflag文のサイズを確保
  • pFVar1 = fopen("enc.txt","w");でenc.txtを書き込み片言で開く
  • sVar3 = fwrite(__ptr,1,__size,pFVar1);+1された文字列を書き込む

つまり、この問題の本質はflagは ROT1でエンコードされているということ

Answer

よってenc.txtをROT1でデコードしてやればいい
Web上でもできそうだが、以下のscriptでデコード

 cat decode.py                                                                                                       ❮❮❮
enc = "tvotijof|lO1x`z1v5`s1nAo`iJ6u1sZ~"

# 1文字ずつASCIIコードを -1
dec = ''.join(chr(ord(c) - 1) for c in enc)

print("Decoded flag:", dec)
python3 decode.py                                                                                                   ❮❮❮
Decoded flag: sunshine{kN0w_y0u4_r0m@n_hI5t0rY}

flag は sunshine{kN0w_y0u4_r0m@n_hI5t0rY}

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?