tmxklab

[Pwnable.xyz] xor 본문

War Game/Pwnable.xyz

[Pwnable.xyz] xor

tmxk4221 2020. 4. 9. 21:07

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로 변환해주는 기능)

 

[pwnable.xyz] xor

이번 문제도 한번도 안 해본 방법(?)인 문제였다. 전체적인 형식은 add나 sub와 똑같아서 세 변수 중 두 변수로 값을 조절하고, 다른 한 변수로는 리턴할 곳을 조절하는 것으로 같았다. 하지만 이번

koharinn.tistory.com

② 직접 call win을 찾는 방법

 

pwnable.xyz / xor

  while ( 1 )   {     n = 0LL;     printf(format);     c = _isoc99_scanf("%ld %ld %ld", &x, &y, &n);         if ( !x || !y || !n || n > 9 || c != 3 ..

mineta.tistory.com

 

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
Comments