본문 바로가기
pwnable

[Toddler's Bottle] bof

by 미스터 J 2024. 5. 11.
반응형

문제시작부터 모르는 것이 나왔다. 처음에 좀 많이 당황했다.

ssh로 진입하는 게 아닌 nc로 진입한다고 한다. 다행이 보안기사를 공부할 때 봤던 내용이다.

입력해보니까 이런식으로 나온다. 아무거나 입력해도 결과는 똑같다.


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
        char overflowme[32];
        printf("overflow me : ");
        gets(overflowme);       // smash me!
        if(key == 0xcafebabe){
                system("/bin/sh");
        }
        else{
                printf("Nah..\n");
        }
}
int main(int argc, char* argv[]){
        func(0xdeadbeef);
        return 0;
}


우선 위의 다운로드 링크를 받아보니 이렇게 나온다. 우선 모르는 것을 정리해 보자.

 

gets() : 표준입력(stdin)으로 들어온 문자열을 C언어 스타일 문자열인 char*, char[] 타입으로 저장해 주는 함수다.

문자열이라고 감지하는 기준은 개햄(\n)이다. 최신 visual studio에서는 gets함수에서 버퍼오버플로우가 발생할 수 있기 때문에 gets_s를 사용하라고 권장한다.

 

주석에 smash me라고 적혀있는 것을 보면 저 부분이 포인트인것 맞는거 같다.

0xcafebabe를 맞춰주면 문제가 해결된다는것.

역시나 되지 않는다. 혹시나 10진수로 변환해서 해봤는데도 그렇다.

 

여기서부터는 write-up을 참고했다. 역시나 어렵다. GDB를 사용해야 하므로 관련 내용을 정리해보자.

BoB에서 교육받을 때 GDB에 대해 가볍게 배웠지만 머릿속에 남아있는 것이 없다.

gdb [program name] [PID] : 프로세스 디버깅

disas : 프로그램의 어셈블리 코드 보기

disas [function] : 함수부분의 disassemble 한 코드를 보여줌

disas [0xffffffffa0] [0xffffffffa9] : 주소 범위 사이의 어셈블리 코드를 보임

b : run(r)명령어가 실행된 후 멈출 메모리 위치

b [function] : 함수 시작 부분에서 break point 설정

cl : 브레이크 포인트를 지울 수 있다.

d : 모든 브레이크 포인트를 지움

ni : 어셈블리 소스의 한줄 실행. 함수가 호출되는 부분도 한줄로 인식.

si : 어셈블리 소스의 한줄을 실행. 함수가 호출되면 함수루틴으로 진입.

q : gdb 종료

우선 가볍게 필요한 내용들만 정리했는데도 상당하다;;

 

산너머산이다;; 이게 뭔일이래....(pwndbg가 더 예쁘게 나와 그것을 설치했다)

우선 disas func 부분에 다음과 같이 나오는것을 확인했다. 

0x00000654 <+40>: cmp    DWORD PTR [ebp+0x8],0xcafebabe

cmp(compare) : 비교 명령어다. cmp는 혼자 사용되지 않고 언제나 조건 점프 명령어나 조건 이동(mov) 명령어와 함께 사용된다고 한다.

어셈블리는 너무 모르는게 많아서 나중에 따로 정리해야겠다.

우선 4번의 call이 보이는데 각각 printf(), gets(), system(), printf() 이다.

get()의 인자로 overflowme가 들어가고 0x00000649 <+29>: lea    eax,[ebp-0x2c]
위치에 있는 것을 확인 할 수 있다.

key는 0xcafebabe와 비교하기 때문에 key는 [ebp + 0x08] 번지에 있는 것을 확인

ebp는 뭘까?

EBP (Extended Base Pointer) : 현재 스택에 가장 바닥을 가리키는 포인터

새로운 함수가 호출될 때마다 EBP 레지스터 값이 지금까지 사용했던 스택 꼭대기의 위에 위치하게 되고 새로운 스택이 시작한다. 따라서 EBP는 새로운 함수가 호출이거나 현재 실행중인 함수가 종료되어 리턴될때마다 값이 달라진다.

우선 2C -  EBP  -  8 이렇게 EBP를 기준으로 나뉘어져있다.

둘사이의 값은 십진수로 52 가 차이 나므로 결국에는 overflow가 있는 주소대신 cafebabe가 있는 주소를 지정해주면 되는 것이다.(이걸 이해하는데 2시간이 걸렸다.... 본격적인 어셈블리 공부가 필요하다.)

0x00000649 <+29>: lea    eax,[ebp-0x2c] 

0x00000654 <+40>: cmp    DWORD PTR [ebp+0x8],0xcafebabe

처음에는 29~40의 차이인줄 알아 11만 오버플로우 해주면 된다고 생각했다.

daddy, I just pwned a buFFer :)

반응형

'pwnable' 카테고리의 다른 글

[Toddler's Bottle] fd  (0) 2024.05.26
[Toddler's Bottle] col  (0) 2024.05.11
[Toddler's Bottle] flag  (0) 2024.05.11
[Toddler's Bottle] passcode  (0) 2024.05.11
[Toddler's Bottle] random  (0) 2024.05.11