picoCTF 2019 Only Binary Exploitation write up
handy-shellcode
소스코드를 확인해 보면 아래와 같습니다.
vuln 함수에 인자값으로 입력값 저장 배열 buf를 가져오는것으로 보아 이곳에 쉘코드를 넣으면 익스가 될것 같다.
하지만 picoctf 는 nc 를 주는것이 아닌 웹 shell을 이용해서 서버에 접근이 가능하다.
그래서 ssh(host='', user='', password='')를 이용해서 서버와 연결을 시키고 문제에 나와있는 디렉토리로 가기 위해서
set_working_directory를 이용해서 이동할 예정입니다.
Flag : picoCTF{h4ndY_d4ndY_sh311c0d3_0b440487}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
practice-run-1
해당 파일은 그냥 실행하면 Flag를 얻을 수 있다.
Flag : picoCTF{g3t_r3adY_2_r3v3r53}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
OverFlow 0
이 문제도 소스코드를 먼저 살펴 보겠습니다.
이 문제에서는 Ret의 값이 변경되면 Segmentation fault 를 출력하게되는데
그 값이 출력되면 sigsegv_handler 함수를 실행하는 문제입니다.
일단 데이터는 argv[1]에 데이터를 집어 넣으면 vuln 함수의 buf를 채울 수 있을 것으로 판단이 됩니다.
그렇다면 일단 vuln함수에 있는 buf의 크기를 확인해 봐야 할 것 같습니다.
0x88 만큼의 크기가 할당 되어 있네요
buf[0x88]
buf-sfp[0x4]
buf-ret[0x4]
input[~~~]
의 형식으로 Stack이 쌓여져 있습니다.
input의 데이터를 buf에 넣기 때문에 input에 0x88+0x4 의 값인 0x8C를 넣으면 그 뒤로 RET의 값을 변조 시킬수 있을 것 같습니다.
0xdeadbeef 는 아무런 의미 없는 값으로 RET 값 변조에 사용된 것 입니다.
Flag : picoCTF{3asY_P3a5y2f814ddc}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
OverFlow 1
소스코드를 확인해 보면 아래와 같습니다.
코드를 보면 vuln 함수에서 gets 함수가 취약한 것을 알 수 있습니다.
buf를 다 채우고 RET에다가 flag함수의 주소를 넣으면 될 것 같습니다.
Flag : picoCTF{n0w_w3r3_ChaNg1ng_r3tURn532066483}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
OverFlow 2
소스코드를 확인해 보겠습니다.
이전 문제와 비슷한 문제 같지만 flag 함수에 인자값이 있습니다.
RTL 기법을 이용해서 같이 넣어 줘야 하는 것 같습니다.
Flag : picoCTF{arg5_and_r3turn598632d70}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
slippery-shellcode
소스코드를 확인해 보겠습니다.
해당 코드에서는 buf에 데이터를 집어 넣는데 offset 이라는 변수가 있습니다.
해당 변수는 rand값을 256으로 나눠서 나머지 +1 을 하고 buf와 더해서 주소를 변환 하게됩니다.
결국 buf+offset 주소를 가지고 있는 곳에 shellcode를 넣어야 합니다.
하지만 offset 값이 랜덤이기 때문에 정확한 위치를 알 수 없습니다.
그래서 제가 사용한 기법은 NOP SLED 입니다.
NOP를 삽입해서 특정 값이 나올때 까지 쭉 스킵하는 기법입니다.
offset의 값이 최대 256 까지 나오기 때문에 NOP 256개를 삽입하고 쉘코드를 넣으면 익스가 될것 같습니다.
Flag : picoCTF{sl1pp3ry_sh311c0d3_5a0fefb6}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
NewOverFlow-1
소스코드를 확인해 보겠습니다.
vuln함수에서 buf를 입력받고 flag 함수에서 flag를 출력해 줍니다.
buf의 크기가 0x40 이고 64비트 환경이여서 "A"*72 + flag 함수 주소를 넣으려고 했으나 flag출력에 실패 했습니다.
↑ 출력에 실패한 코드
그 이유를 알아보니 서버 웹쉘 에서 18.04 우분투 버전을 사용하고 있어서 printf 와 같은 함수를 호출할때 문제점이 생긴다고 합니다.
printf 함수 내부에서 어셈을 하나더 추가가 되서 사용하는데 그 값이 16바이트로 정렬이 되어 있어야 한다고 합니다.
하지만 지금 정렬이 되지 않아서 ret gadget을 이용해서 flag함수를 호출 할 수 있다고 합니다.
그래서 아래와 같은 코드를 작성 했습니다.
Flag : picoCTF{th4t_w4snt_t00_d1ff3r3nt_r1ghT?_351346a2}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
NewOverFlow-2
소스코드를 확인해 보면 아래와 같습니다.
저번에 풀던 NewOverFlow-1 문제와 매우 유사하지만 똑같은 방식으로도 flag를 출력할 수 있을 것 같습니다.
Flag : picoCTF{r0p_1t_d0nT_st0p_1t_e51a1ea0}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
제가 푼 문제들이 전부가 아닙니다.
제가 개인 공부를 해야해서 개인 사정으로 인해 풀다가 만것이기 때문에
직접 사이트에 들어가셔서 즐햌 하시길 바랍니다!!