안 쓰던 블로그
64it ROP 본문
gdb 켜서 전역변수 리스트 확인
/bin/sh 주소인 0x0000000000004038 확인
함수 정보 확인
main, nothing, vuln
main확인
vuln 함수가 있다
vuln 함수 확인
read를 사용했다
nothing 확인
첫 번째 인자를 받는 레지스터인 rdi
rdi를 push
rdi를 pop후 return
rdi에 원하는 값을 넣으면 return되면서 되겠다
pop rdi 가젯:
pop rdi; ret 가젯을 이용하여 첫번째 인자를 받는 레지스터인 rdi에 전역변수 sh의 주소를 넣은 뒤 system 함수를 ret 하면 쉘이 실행 됩니다.
익스플로잇 코드
먼저 ida등에서 버퍼가 16이라는 사실을 알고 있다 16+8=24만큼 더미를 넣는다
하지만 64bit는 다르다... 64bit에서는 6개짜기의 인자가 레지스터에 들어간다.
첫번째 인자는 rdi 레지스터에 들어가고, 순서는 아래와 같다.
-----register field-----
rdi : 첫번째인자
rsi: 두번째인자
rdx: 세번째인자
rcx: 네번째인자
r8: 다섯번째인자
r9: 여섯번째인자
-------stack field-------
r10(%rsp): 일곱번째인자
r11, 0x8(%rsp): 여덟번째인자
r12
....
[64BIT CALLING CONVENTION]
- function@plt + rdi + rsi + rdx + rcx
그래서 스택에는 인자가 따로 들어가지않는다.
bof가 나서 프로그램이 죽으면 ret instruction에서 죽게되는데(이걸 몰라서 계속 여기서 죽는데 지금까지 이유를 몰랐다.)
보통은 rsp가 잘못되거나 rsp가 가리키는 값(rip가 되는값)이 잘못되었기 때문인데...
여기서 인자를 32bit처럼 올려주고 실행하려고 하면 당연히 인자는 rdi레지스터부터 가져오므로 잘못된 호출로 죽게된다. (스택은 아무의미가 없다 ㅡㅡ;)
그러므로 함수호출전에 pop rdi 같은 가젯들을 이용해 인자를 넣어주는게 좋다.