tmxklab
[HackCTF/Pwnable] Offset 본문
1. 문제확인
nc ctf.j0n9hyun.xyz 3007
1) 접속
- 문자열 출력과 동시에 프로그램은 아무런 수행없이 종료
2) IDA(Pseudocode)확인 - main()
- main()의 인자 개수(argc)를 v5에 저장
- gets()를 통해 표준 입력 값을 s변수에 저장한 뒤, select_func()의 파라미터로 전달
3) IDA(Pseudocode)확인 - select_func()
- 함수 포인터 v3 선언 후 two()로 초기화
- strncpy()를 통해 31bytes(0x1Fu)만큼 파라미터 src값을 dest로 복사
- if문에서 dest변수에 저장된 문자열과 "one"이 같으면 함수 포인터 v3에 one()주소로 저장
- return값으로 v3()함수 포인터 반환
4) IDA(Pseudocode)확인 - print_flag()
- flag.txt파일을 읽기모드로 열어 1byte씩 화면에 표준 출력
- 실행시켜야할 함수
5) IDA(Pseudocode)확인 - one(), two()
- puts()를 통해 문자열 출력
6) $checksec를 통해 elf파일에 걸린 메모리 보호기법 확인
- RELRO : Relocation Read-Only의 줄임말로 GOT Overwirte와 같은 공격에 대비하여 elf바이너리 또는 프로세스의 데이터 섹션을 보호하는 기술, 즉, 메모리가 변경되는 것을 보호, Full RELRO으로 걸려있으면 .ctors, .dtors, .jcr, .dynamic, .got섹션이 읽기 전용 상태가 됨
- NX : 리눅스 보호기법중 DEP(Data Execution Prevention)로 데이터 영역에서 코드가 실행되는 것을 막는 기법, 예를 들어 DEP가 적용된 경우 bof공격을 통해 return address를 변조했을 때 실행권한이 없어 쉘코드가 실행되지 않고 프로그램에 대한 예외처리 후 종료됨
- PIE : Position Independent Executable의 줄임말로 위치 독립 실행파일, 실행할 때마다 매핑되는 주소가 어디든지 상관없이 실행되는 파일로 매핑되는 주소가 매번달라 바이너리의 주소를 랜덤화하여 바이너리의 특정 주소의 값을 수정하는 것과 같은 공격을 방어
- Stack Canary : 함수 진입 시 스택에 SFP와 return address정보를 저장할 때, 이 정보들이 공격자에 의해 덮어씌어지는 것으로부터 보호하기 위해 스택상의 변수들의 공간과 SFP사이에 특정한 값을 추가하는데 이 값을 canary라고 불림, 예를 들어 bof공격시 return address를 덮기 전에 canary값이 먼저 덮어지므로 canary값의 변조 유무로 bof 탐지 가능
- 따라서, 현재 RELRO가 적용되어 GOT Overwrite가 불가능하고 PIE가 적용되어 바이너리 주소 값을 수정하는 공격이 불가능하고 NX가 걸려 DEP보호기법이 작동중인 상태
2. 접근방법
- 결과적으로 main()에서 실행하지 않은 printf_flag()를 실행시켜야 함
- 메모리 보호기법이 다수 걸려있는 상태에서 먼저 main()에서 입력 값을 받고 처리하는 select_func()분석
1) 스택구조(select_func)
- strncpy()를 통해 파라미터이자 입력 값인 src변수의 내용을 dest변수로 복사
- 이때, 31bytes까지 복사할 수 있는데 스택구조를 보면 dest와 v3사이에 30bytes 차이 발생
- 따라서, 31bytes를 꽉 채워서 입력하면 1byte만큼 v3변수를 덮어씌울 수 있음
- 또한, v3는 two()의 주소를 담은 포인터이며 함수의 return값
2) two()와 print_flag()비교
- two()의 시작주소 : 0x000006AD -> \xAD\x06\x00\x00
- flag_print()의 시작주소 : 0x000006D8 -> \xD8\x06\x00\x00
3) 결론
- strncpy()를 통해 v3변수에서 1byte만큼 변조 가능
- 실행시켜야할 flag_print()와 v3변수에 초기화된 two()의 각각 주소는 1byte만 차이남
- 따라서, 30bytes의 더미 값과 1byte인 \xD8을 사용하여 flag_print()를 실행
- dummy(30bytes) + \xD8(1byte)입력 시
3. 풀이
1) 공격 코드 작성
from pwn import * # pwntools모듈
# remote(ip, port), ip는 string형, port는 int형
p = remote("ctf.j0n9hyun.xyz", 3007)
p.recvuntil("Which function would you like to call?")
payload = "A"*30
payload += "\xD8"
p.sendline(paylaod)
# interactive()는 쉘과 직접적으로 명령을 송수신할 수 있는 함수
p.interactive()
2) 공격실행
'War Game > HackCTF' 카테고리의 다른 글
[HackCTF/Pwnable] Yes or no (0) | 2020.02.22 |
---|---|
[HackCTF/Pwnable] BOF_PIE (0) | 2020.01.28 |
[HackCTF/Pwnable] Simple_Overflow_ver_2 (0) | 2020.01.27 |
[HackCTF/Pwnable] x64 Simple_size_BOF (0) | 2020.01.27 |
[HackCTF/Pwnable] x64 Buffer Overflow (0) | 2020.01.27 |
Comments