tmxklab
[Pwnable.xyz] xor 본문
1. 문제
nc svc.pwnable.xyz 30029
1) 문제 확인
- 세 개의 입력 값을 받고 결과를 출력해주는 프로그램
2) 함수 확인
2-1) IDA(hex-lay) - 메인 함수
- v4, v5, v6에 입력 값을 받아 result[v6]의 값을 출력
- result[v6] = v5 (xor) v4
2-2) IDA(hex-lay) - win함수
3) 메모리 보호기법 및 파일 정보 확인
2. 접근 방법
먼저, 가장 눈에 띄는 부분은 이 부분이다.(main함수 line 19)
xor 계산한 값을 result[v6]에 저장하는 로직이다.
따라서, result의 인덱스와 값을 조작할 수 있다.(원하는 주소와 해당 주소에 값을 지정할 수 있음)
그리고 result는 main함수에서 선언한 변수가 아니라 전역변수임을 확인할 수 있다.
또 하나 main함수 바로 위에 win함수가 존재하는 것을 알 수 있다.
우리가 결국 해야할 것은 win함수를 호출하는 것이다.
처음 생각한 것은 result를 이용하여 main함수의 ret에 win함수를 호출하는 간단한 방법을 생각했다.
-
하지만, 조건문을 만족하지 않으면 exit함수를 호출하면서 종료하여 ret가 보이지 않는다.
다시 정리하면...
1. result를 사용하여 원하는 주소에 값을 저장할 수 있다.
2. main함수에 ret는 존재하지 않고 call exit를 통해 종료한다.
3. main함수 바로 위에 win함수가 존재한다.(main : 0xa34, win : 0xa21)
4. result는 bss영역에 존재한다.(result : 0x202200)
그럼 main함수의 call exit대신에 call win을 생각해 볼 수 있다.
그러기 위해선 다음 2가지를 확인해봐야 한다.
1. result[v6]를 통해서 main함수의 call exit instruction이 존재한다. 0x8000ac8에 접근할 수 있는지
2. instruction을 변경(call exit -> call win)할 수 있는지 확인해봐야 한다.
디버깅)
먼저 디버깅을 통해 확인해보자
(입력 값은 1, 1, 1을 주었다.)
- v6[rbp-0x10] -> rax // v5[rbp-0x18] -> rdx // v4[rbp-0x20] -> rcx
- rcx(v4)와 rdx(v5)가 xor연산하여 rcx[xor결과 값)에 저장
-
rax(v6)에 8을 곱하여 rdx에 저장
-
rax(v6)에 [0x8202200](result주소 값)저장
-
rdx(v6*8)와 rax(result)에 rcx값을 복사
즉, [v6 * 8 + 0x8202200] 위치에 xor한 결과 값을 넣는 것이다.
확인1) vmmap을 통해 권한 확인
-
코드(텍스트)영역은 실행할 프로그램의 코드가 저장되는 영역
-
현재 0x8000000 ~ 0x8001000이 rwxp로 설정되어 있어 모든 권한이 가능하다.
-
그리고 해당 영역에 main함수와 win함수의 instruction이 포함된다.
-
win() : 0x8000a21
-
main() : 0x8000a34
확인2) result[v6] 조작
이제 result[v6]를 통해서 main함수의 call exit가 위치한 곳을 참조할 수 있는지 확인해보자
-
0x8000ac8 : call exit
[v6*8 + 0x8202200] = 0x8000ac8(call exit)이므로
v6 = (0x8000ac8 - 0x8202200) / 8
따라서, v6는 0xfffffffffffbfd19이며 십진수로는 -262,887이다.(v6 = -262,887)
그럼 입력 값을 (1, 1, -262,887)을 주어 확인해보자
-
call exit 부분이 사라지고 xor결과 값인 0이 삽입되었다.
결론)
-
result를 이용하여 main함수의 call exit 인스트럭션을 call win으로 변경
3. 풀이
이제 필요한 것은 call win의 인스트럭션 값을 구하는 것이다.
또한 result[v6]에 v4와 v5의 xor 계산 결과 값을 넣는 것이므로 v4와 v5를 알맞게 수정해야한다.
1) call exit → call win
방법이 두 가지가 존재한다.
① pwntools를 사용하는 방법(pwnlib.asm moudle : disassmble을 assemble로 변환해주는 기능)
② 직접 call win을 찾는 방법
2) 확인
v4 = 1
v5 = 0xFF 0xFF 0xFF 0x54 0xE8 → 1,099,511,583,976
v6 = -262,887
-
jmp win으로 바뀐 것을 확인할 수 있다.
3) 공격 실행
4. 몰랐던 개념
직접 call win을 찾을 때,
x86-64에서 PIE가 걸려있는 경우 RIP relative addressing기법을 사용
call exit;를 실행하는 시점에서 rip=0xacd이며 win의 주소는 0xa21이므로
0xacd-0xa21 = 0xac → -0xac = 0xFFFF FFFF FFFF FF54
즉, call 0xFFFF FFFF FFFF FF54
call은 e8이므로 assemble하면 e8 54 ff ff ff
'War Game > Pwnable.xyz' 카테고리의 다른 글
[Pwnable.xyz] TLSv00 (0) | 2020.04.09 |
---|---|
[Pwnable.xyz] two target (0) | 2020.04.09 |
[Pwnable.xyz] note (0) | 2020.04.09 |
[Pwnable.xyz] free spirit (0) | 2020.03.30 |
[Pwnable.xyz] grownup (0) | 2020.03.30 |