[pwnable.xyz] Welcome(50 pts) :: Write-Up

두비니

·

2019. 11. 1. 16:39

Are you worthy to continue?

 

 

 

 

처음에 출력해주는 주소는 v3을 malloc하여 얻은 주소로, 여기를 0으로 만드는게 목적이다. 다른 곳들에 올라와있는 write-up들을 보면 모두 size에 큰 값을 넣어주게 되면 malloc의 리턴 값이 0이 되기 때문에 내가 원하는 주소를 0으로 수정할 수 있다. 하고 끝나던데 이 한줄로 이해가 된다고?????

 

해킹하는놈들은 천재밖에 없냐??????

 

그래서 저는 삽질을 추가로 했습니다.

 

 

아이다로 분석을 해보면 내가 입력하는 데이터도 heap로 들어가고, stack canary도 활성화 되어있어서 '과연 welcome문제인데 canary leak까지 이용을 할까...?'라는 생각으로 stack을 보기보다는 실제 프로그램이 돌아가는 것을 보았다.

다음은 gdb로 까서 일단 실행시켜 본 후 어어어엄청 큰 값을 넣어보았다. 당연히 segmentation fault가 뜨고, 위 캡쳐에서는 없지만 peda에서 제공하는 registers밑에 code영역에 가보면

 

 

=> 0x5555555549d6:    mov    BYTE PTR [rbp+rdx*1-0x1],0x0

    0x5555555549db:    call   0x5555555548b8        #if문 분기점

다음과 같은 instructions를 보여준다. (peda는 저렇게 segmentation fault가 뜨면 일어난 곳을 화살표로 알려줍니다.)

 

근데 rbp와 rdx값을 확인해보면

 

 

 

각각 0과 -1이다.

 

 

어셈 코드를 까본 결과, rdx는 내가 입력한 값인 size가 들어가는 자리인데, 만약 malloc에 실패하면 rbp에는 0이 대입되게 된다. 즉, 내가 rdx값만 조절해 줄 수 있다면 cat flag를 실행시킬 수 있다. 추가로 설명하자면 이 경우에는 -1이라는 주소는 존재하지 않기때문에 segmentation fault가 발생한 것이다.

 

그러면! 이미 rbp는 0이므로 rdx에는 (내가 실행하고 싶은 주소값) + 1을 입력하면 내가 원하는 주소값에 0을 집어넣을 수 있다.

따라서 (leak으로 얻은 주소의 10진수값) + 1을 넣었다! (아참, payload로 입력한 주소의 10진수값도 너무 크기때문에 rbp의 값은 0이된다.

 

 

 

==FINAL PAYLOAD==

 

 

솔직히 첫번째 문제치고는 난이도가 상당히 높았다고 생각한다. 근데 플래그를 보고 상당히 충격을 먹었다...ㅎㅎ 과정이 상당히 간단하긴 했지만 malloc의 리턴값이 0일때 그 할당받은 포인터의 상황이 어떻게 되는지 알지 못한다면 어려웠을 것 같다. 아니 그걸 어떻게....

 

나의 공부량이 부족한걸로 하자. next!

 

 

 

+) 그땐 몰랐지만 이제는 알아서 쓰는 것들

 

그때 이 문제를 풀었을 당시 푸는거 자체에 급급해서 정확하게 이해하고 넘어가지 못하였다. 추가적으로 알고있어야 좀 말이 되는 정도로 풀 수 있다고 생각해서 추가해서 쓴다.

 

 

1. malloc함수의 리턴값

 

  이건 애초에 모른다면 풀 수 없었긴 한데, 일단 malloc함수의 원형이다.

void *malloc(size_t _Size);

  그리고 malloc함수는 할당한 주소를 return한다. 그러나 할당할 수 없는 만큼을 할당한 경우(ex. 너무 많이..)는 어떻게 될까?

그러면 void pointer(0)을 리턴하게 된다. 그래서 malloc의 최대 할당 가능 크기를 찾아보았다.

 

출처 : ibm

물론 이건 컴퓨터마다 사정이 다르긴 하지만, ibm에서는 16메가바이트가 최대라고 한다.... 좀 이상해서 내 우분투로 이것저것 해봤는데 1기가 조금 안되게 할당이 되었다. 그냥 케바케인거같다.

근데 아무튼 이 문제에서 쓰인 0x7ffff7f9b010은 값이 어마어마하게 크기때문에 어차피 리턴값은 0이다.

 

 

2. NO Binary(Binary Stripped)

 

기존의 문제풀이를 보면 그냥 중간에 브포걸고 어셈을 확인하는 식으로 풀이가 진행된다.

당시에는 gdb에서 info funcdisas main같은게 안되길래 그냥 내가 뭔가 잘못했겠군 하면서 넘어갔다. 근데 이건 컴파일할때 설정할 수 있는 부분이다. 그래서 "디버깅 심볼"을 포함시키지 않고 컴파일한것이다. 물론 그래봤자 main startup routine확인을 통해서 구할 수는 있다. 간단한 내용이지만 그때의 나처럼 모르는 사람들이 있을수 있으니까...;-;

 

그리고 이부분은 main함수의 구동 과정과도 관련이 있기 때문에 이부분 관련해서 글을 새로 쓰도록 할것입니다.

참고: umbum.tistory.com/103?category=711929

 

main startup routine bt

`` main``의 상위 frame은 `` __libc_start_main``이다. __libc_start_main `` __libc_start_main``은 `` init, fini, stack_end`` 등을 인자로 받는데, 첫 번째 인자로 `` main``의 함수 포인터를 받는다. ```c..

umbum.dev

 

 

추가로 이분것도 라업 좋은듯

lactea.kr/entry/pwnablexyz-Welcome-write-up

 

[pwnable.xyz] Welcome write up

pwnable.xyz 사이트의 첫번째 문제 Welcome 문제이다, Excute 우선 실행해보면 아래 처럼 출력이 되는 것을 볼 수 있다. ubuntu:~/environment/ctf/pwnable.xyz/01_welcome/image/challenge $ ./challenge Welcom..

lactea.kr

 

사실 지금보니깐 너무 자명한데 그땐 그랬지,,, 

얼른 이거 관련해서 개념글 써야겠다.