드림핵에는 64bit만 나와있어서 따로 찾아보게 됬고 이번에 배운 것에 대하여 쓸려고 한다
!위에 사진에 문제가 있네요 3번째 그림에서 맨 왼쪽 한칸이 없다고 생각해야합니다!
bof가 터진다는 가정 하에 첫번째 그림처럼 덮어준다면 두번째 그림처럼 되게 된다
그 이유는 ret자리에 system함수의 주소를 덮어준다면 call을 통해 인자를 스택에 쌓고 호출하는 것이 아닌
RET의 POP EIP, JMP EIP를 통해 call없이 넘어가지만 함수에서는 당연히 call을 통해 인자를 스택에 쌓고 부른 줄 알고
PUSH EBP / MOV EBP, ESP가 실행되고 sfp(ebp)+8번 부터 인자를 가져올 것이기에 system함수가 호출된 후에 RET자리
가 될 곳에 dummy를 넣어준 후 인자(/bin/sh)을 넣어주게 되는 것이다
ropx86은 rtl코드 부분 중 dummy에 적절한 코드 가젯을 넣어주어 스택을 정리하게 해서 연속으로 함수를 호출할 수 있게 하는 것이다
먼저 예제로 설명을 해보겠다
puts = puts함수의 주소
read = read함수의 주소
pr = pop edi; ret;
ppr = pop esi; pop edx; ret;
pppr = pop ecx; pop edx; pop esi; ret;
payload = dummy #sfp까지 덮어주는거
#첫번째 cycle
payload += p32(puts)
payload += p32(pr)
payload += p32(raedableadr) => puts(raedableadr) 실행
#두번째 cycle
payload += p32(read)
payload += dummy #다음으로 실행할 함수가 없으니 스택을 정리하지 않아도 됨
payload += p32(0)
payload += p32(writeableadr)
payload += p32(100) => read(0,writeableadr,100) 실행
puts에서 ret부분에 pop edi; ret;가젯을 넣어주었는데
그 이유는 puts의 인자는 readableadr로 스택에 남아있기에 pop edi;로 없애준다음 ret로 다음 함수 read를 실행시켜주었다
이 때 꼭 edi여야하는 것은 아니고 아무 레지스터든 상관이 없다 (그냥 스택에서 빼는거임)
puts다음 read함수는 ret자리에 dummy를 넣었는데, 그 이유는 마지막 사이클이기에 스택을 정리할 필요가 없기 때문이다
만약 read다음에 새로운 함수를 호출해야 한다면 dummy부분에 pppr(pop 레지스터; pop 레지스터; pop 레지스터; ret)
를 넣어 인자 세 개만큼 스택을 정리해줘야한다 (인자가 한개면 pr, 인자가 두 개면 ppr, 인자가 세 개면 pppr)
'포너블(pwn)' 카테고리의 다른 글
malloc_hook, free_hook offset 구하는 법(번외로 stdout도) (0) | 2022.03.07 |
---|---|
펌) One Gadget 설치 및 사용법 (0) | 2022.03.07 |
서버의 라이브러리 버전 알아내는 법 (0) | 2022.02.25 |
리눅스) 라이브러리 검색 (0) | 2022.02.23 |
RTL ret가젯은 언제 넣어줘야하나? (0) | 2022.02.19 |