Hacking/Pwnable

GOT Overwrite

GunP4ng 2024. 6. 30. 22:56

GOT Overwrite


1. GOT Overwrite

1. GOT Overwrite 과정

함수를 처음 호출하면 PLT 가 호출되고 PLTGOT 로 점프한다.

 

첫 번째 호출이면 GOT 에 함수의 실제 주소가 쓰여있지 않아

dl_resolve 함수가 실제 함수의 주소를 알아와 GOT 에 써준 뒤 함수를 호출한다.

 

두 번째 호출부터는 PLTGOT 로 점프하여 함수의 실제 주소를 가져온다.

이 때 PLTGOT 에 적힌 주소를 검증하지 않고 가져온다.

 

GOT변조하게 되면 공격자가 원하는 함수를 실행할 수 있다.

이러한 공격 기법을 GOT Overwrite 라고 한다.

 

2. GOT Overwrite 실습

//Name : got.c
//Compile : gcc -o got got.c -fno-stack-protector -z -execstack -no-pie -m32

#include <stdio.h>

void main() {
    puts("pwd");
}

pwd 를 출력하고 종료되는 코드이다.

 

여기서 puts 함수의 GOTsystem 함수의 주소로 덮는다면,

puts 함수 호출 시, GOT 에 저장된 주소를 puts 함수의 주소로 인식하여 system 함수를 실행하게 된다.

gdb 를 통해 확인해보자

 

Dump of assembler code for function main:
   0x08049176 <+0>:     lea    ecx,[esp+0x4]
   0x0804917a <+4>:     and    esp,0xfffffff0
   0x0804917d <+7>:     push   DWORD PTR [ecx-0x4]
   0x08049180 <+10>:    push   ebp
   0x08049181 <+11>:    mov    ebp,esp
   0x08049183 <+13>:    push   ebx
   0x08049184 <+14>:    push   ecx
   0x08049185 <+15>:    call   0x80491ae <__x86.get_pc_thunk.ax>
   0x0804918a <+20>:    add    eax,0x2e76
   0x0804918f <+25>:    sub    esp,0xc
   0x08049192 <+28>:    lea    edx,[eax-0x1ff8]
   0x08049198 <+34>:    push   edx
   0x08049199 <+35>:    mov    ebx,eax
   0x0804919b <+37>:    call   0x8049050 <puts@plt>
   0x080491a0 <+42>:    add    esp,0x10
   0x080491a3 <+45>:    nop
   0x080491a4 <+46>:    lea    esp,[ebp-0x8]
   0x080491a7 <+49>:    pop    ecx
   0x080491a8 <+50>:    pop    ebx
   0x080491a9 <+51>:    pop    ebp
   0x080491aa <+52>:    lea    esp,[ecx-0x4]
   0x080491ad <+55>:    ret
End of assembler dump.

main 함수의 어셈블리다.

puts 함수를 호출하는 부분에 break 를 걸고 실행한다.

 

break puts

puts 함수가 호출하는 주소 0x8049050 을 확인해보자

함수가 처음 호출 되기 때문에 puts 함수의 GOT 에는 puts 함수의 실제 주소가 아닌 PLT+6 주소가 들어있다.

 

여기서 puts 함수의 GOTsystem 함수의 주소를 넣으면

puts 함수 실행 시 GOT 에 들어있는 system 함수로 점프하여 system 함수가 실행될 것이다.

system

system 함수의 주소는 0xf7dca170 인 것을 확인할 수 있다.

이제 puts 함수의 GOT 0x804c010system 함수의 주소로 덮어씌우자

 

system 함수 주소로 덮어씌우기

gdb 에서 set 명령어를 이용하면 원하는 주소를 덮어씌울 수 있다.

 

continue 를 하게 되면

pwd 명령이 실행된 것을 확인할 수 있다.

 

 

Reference


https://blackperl-security.gitlab.io/blog/2016/05/02/2016-05-02-linux-02/