생초보 pwnable.kr - blukat write-up
1. GDB
GDB는 프로그램 수행 중 프로그램 내부가 어떻게 진행되고 있는지를 파악하게 해주는 디버거입니다. 리눅스에서는 기본적으로 제공하며 C, C++로 만든 프로그램을 디버깅할 수 있습니다. 여기서는 문제 푸는데 필요한 명령어와 중요한 명령어만 간단히 소개해드리겠습니다.
- GDB 시작
$gdb [프로그램명] - 가장 일반적인 시작 방법
- GDB 명령어
명령어 | 설명 |
run | 프로그램을 처음부터 시작합니다. |
break [라인 넘버] | 해당하는 라인에 break point를 겁니다. |
break [함수명] | 해당 함수에 break point를 겁니다. |
break *주소 | 해당 주소에 break point를 겁니다. |
print(x)/[포맷] [변수] | 변수에 해당하는 값을 보여줍니다. |
disas [함수명] | 해당 함수의 디스어셈블된 코드를 보여줍니다. |
set disassembly-flavor intel | 디스어셈블된 코드가 인텔 문법 형식으로 나옵니다. |
-print 포맷
Write-Up
이번 문제는 3점짜리 blukat 문제입니다. 제목이 뭘 뜻하는지는 잘 모르겠네요.
문제 내용을 보면 힌트를 주는데 숙련된 사용자에게는 어렵다는 거 같네요. 쉽게 생각해야 되는 문제 같습니다.
이번 문제는 flag가 아니라 password 파일이 있네요. 어쨌든 blukat.c를 봐보겠습니다.
코드 내용은 password 파일을 열어서 password 버퍼에 넣고 사용자 입력으로 buf에 넣고 password 버퍼와 buf 버퍼를 비교해서 같으면 calc_flag(password) 함수로 넘어갑니다. calc_flag() 함수는 password 버퍼를 인자로 받아서 key값과 한 글자씩 xor 연산해 flag 버퍼를 채워 넣습니다. 그리고 마지막에 조합된 flag를 알려주네요.
자 우선 저는 아마도 gdb를 통해 password 버퍼를 뒤지면 무언가 나올 거라 생각했습니다.
password 버퍼는 처음 나오는 fgets와 strcmp에 공통으로 사용되므로 두 부분에서 모두 나오는 주솟값을 통해 0x6010a0이 password 버퍼라고 추측했습니다. 근데 두 번째 fgets에서는 rax가 인자로 사용됐는데 첫 번째 fgets에서는 edi가 사용되는 게 좀 의문이네요. 전역변수와 지역변수의 접근 차이일까 생각해 봅니다.
어쨌든 찾았으니 0x40083a 즈음 break를 걸고 봐보겠습니다.
봐보니 이상한 Permission denied 메시지가 뜹니다. 이때 들었던 생각은 아 이게 password 버퍼가 아니라 password 파일에 대한 주소인가 생각했는데 strcmp부분에는 password 파일이 쓰이지 않았으니까 그럴 리가 없습니다. 그래서 다른 포맷으로도 보았는데 그냥 저런 문자열이 들어가 있는 거였습니다.
하하 재밌는 문제네요. password가 이거니 똑같이 입력해 주면 되겠죠.
After Review
gdb로 변수에 접근해서 볼 수 있으면 어려운 문제는 아닙니다만 장난이 섞여있어서 속으면 산으로 가는 문제였습니다. 발상 자체가 재밌네요. 문제 제목도 그렇고 flag로 나온 please dont miss your group perm이 무슨 뜻인지도 궁금하네요.