주어진 파일을 실행시켜보면, 0~3 사이의 숫자를 입력하여 기능을 하게끔 되어 있다.
IDA를 통해 살펴보니,
(1) 은 malloc을 통해 heap에 입력값을 저장하는 용도로 보이며,
(2)는 저장되어 있는 쉘코드를 지우는 용도,
(3)은 그 쉘코드를 실행하는 용도이다.
그런데, main함수에서 (1)~(3) 기능의 함수를 불러올 때 항상 동일한 &v6을 인자로 주며,
그 위치에는 이미 특정 코드가 저장되어 있었다.
현재 저장되어 있는 Demo-shellcode를 찾아보니, 0x59byte만큼 특정 부분을 stdout하는 형태이다.
실제로 실행시켜보니 위와 같은 문구가 write에 의해 출력되었다. 이부분이 어디에 저장되어 있는지 살펴보니,
.rodata영역에 저장되어 있었다. 그리고, 그 문구 조금 더 밑을 보니 여기에 Flag가 저장되어 있다는 정보를 찾을 수 있다.
이제 정보를 알았으니 시나리오를 짜보면,
우선 현재 쉘코드를 delete를 통해 지우고, 다시 원하는 쉘코드를 입력하면 UAF에 의해 내가 원하는 쉘코드를 실행될 것이다. 그리고 그 쉘코드는 현재 주어진 write함수 그대로 사용하되, 읽는 크기만 0x59에서 0x100정도로 더 크게 해주면 플래그를 읽을 수 있다.
이 시나리오대로 하려고 했으나,
downloadShellcode 함수에서 입력을 받을 때 거치는 verifyUrl 함수에 의해 계속 필터링 되었다.
만약 저기서 0을 return하게 되면, exit(-1)이 실행된다.
위 필터링의 우회는 생각보다 단순하게 해결된다.
if문을 우회하는 것이 아니라, for문을 우회하였는데, (BYTE )(i + al) =0 이면, 위 반복문은 실행되지 않는다.
그래서 입력하는 Url의 앞에 \x00, 즉 NULL을 넣어주면 우회될 것이다.
이제 시나리오 대로 shellcode를 만들어 보자.
쉘코드는 문제에서 주어진 부분에서, \x00을 넣기 위해 'push 0'을 앞에 넣어 주고,
"mov edx, 0x59"를 "mov edx ,0x200"으로 바꿔주어 뒤에 플래그까지 읽히도록 쉘코드를 작성했다.
이 shell코드를 입력하여 실행시켜보니, Flag부분을 읽을 수 있었다.
'CTF > CTF_writeup' 카테고리의 다른 글
[zer0pts] diysig (0) | 2020.03.12 |
---|---|
[zer0pts] ROR (0) | 2020.03.12 |
[CODEGATE 2020 예선] Halffeed (0) | 2020.02.09 |
[Hack.lu CTF 2019] Chat (0) | 2020.02.09 |
[justCTF 2019] ATM service (0) | 2020.02.09 |