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 StringsでYou got it, submit the flag!を検索する
あった
FUN_001014d1で実行されているようなので、Symbol TreeのFunctionsからその関数を探す
デコンパイルの結果が以下
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でデコンパイル
Ghidraで文字列検索すると、FUN_001010a0で動いている関数であることが分かった
Symbol Tree > Functions から該当の関数を見る
検証
デコンパイルしたソースは以下
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_00102013が Labelか.dataにあるかもしれない
SymbolTreeとProgram Treeから見ていく
なかった
デコンパイルした上記の文の引数をクリックしたら飛べた
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でデコンパイルする
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}





