(gdb) disas main
Dump of assembler code for function main:
0x08049844 <main+0>: push ebp
0x08049845 <main+1>: mov ebp,esp
0x08049847 <main+3>: and esp,0xfffffff0
0x0804984a <main+6>: sub esp,0x20
0x0804984d <main+9>: mov DWORD PTR [esp+0x8],0x3e7
0x08049855 <main+17>: mov DWORD PTR [esp+0x4],0x3e7
0x0804985d <main+25>: mov DWORD PTR [esp],0x8049cdc
0x08049864 <main+32>: call 0x8048eb8 <background_process>
0x08049869 <main+37>: mov DWORD PTR [esp],0xbb7
0x08049870 <main+44>: call 0x8049355 <serve_forever>
0x08049875 <main+49>: mov DWORD PTR [esp+0x18],eax
0x08049879 <main+53>: mov eax,DWORD PTR [esp+0x18]
0x0804987d <main+57>: mov DWORD PTR [esp],eax
0x08049880 <main+60>: call 0x8049435 <set_io>
0x08049885 <main+65>: mov DWORD PTR [esp],0x0
0x0804988c <main+72>: call 0x8048c38 <time@plt>
0x08049891 <main+77>: mov DWORD PTR [esp],eax
0x08049894 <main+80>: call 0x8048bf8 <srandom@plt>
0x08049899 <main+85>: call 0x80497ba <run>
0x0804989e <main+90>: leave
0x0804989f <main+91>: ret
음 크게봤을때 main소스 구조는..
int main(){
background_process("net0", 0x3e7, 0x3e7); // 0x3e7 = 999
//각각 name, uid, gid
result = serve_forever(0xbb7); //0xbb7 = 2999
set_io(result);
srandom(time(NULL));
}
이렇게되나보다.
핵심은 background_process랑 serve_forever인데 어차피 나중에 또 나올것 같으니 분석해보자
//argv1 = esp+0x8 "net0"
//argv2 = esp+0x4 0x3e7
//argv3 = esp 0x3e7
(gdb) disas background_process
Dump of assembler code for function background_process:
0x08048eb8 <background_process+0>: push ebp
0x08048eb9 <background_process+1>: mov ebp,esp
0x08048ebb <background_process+3>: push ebx
0x08048ebc <background_process+4>: sub esp,0x224
0x08048ec2 <background_process+10>: mov eax,DWORD PTR [ebp+0x8]
0x08048ec5 <background_process+13>: mov DWORD PTR [esp],eax
0x08048ec8 <background_process+16>: call 0x8048e0d <validate_name>
//validate_name(argv1)
이 함수를 한번 보장
(gdb) disas validate_name
Dump of assembler code for function validate_name:
0x08048e0d <validate_name+0>: push ebp
0x08048e0e <validate_name+1>: mov ebp,esp
0x08048e10 <validate_name+3>: sub esp,0x28
0x08048e13 <validate_name+6>: mov DWORD PTR [ebp-0xc],0x0 //변수 할당 후 초기화
0x08048e1a <validate_name+13>: jmp 0x8048ea5 <validate_name+152>
0x08048e1f <validate_name+18>: mov eax,DWORD PTR [ebp-0xc] //0
0x08048e22 <validate_name+21>: add eax,DWORD PTR [ebp+0x8] //argv1
0x08048e25 <validate_name+24>: movzx eax,BYTE PTR [eax] //첫 바이트 "n"
0x08048e28 <validate_name+27>: cmp al,0x60
0x08048e2a <validate_name+29>: jle 0x8048e39 <validate_name+44>
// al <= 0x60 조건이면 +44로 점프
(일단 n은 0x6e니까 점프 안함)
0x08048e2c <validate_name+31>: mov eax,DWORD PTR [ebp-0xc]
0x08048e2f <validate_name+34>: add eax,DWORD PTR [ebp+0x8]
0x08048e32 <validate_name+37>: movzx eax,BYTE PTR [eax]
0x08048e35 <validate_name+40>: cmp al,0x7a
0x08048e37 <validate_name+42>: jle 0x8048ea1 <validate_name+148>
//if(al <= 0x7a){ jmp +148 }
//0x6e니까 여기서 점프될듯
0x08048e39 <validate_name+44>: mov eax,DWORD PTR [ebp-0xc]
0x08048e3c <validate_name+47>: add eax,DWORD PTR [ebp+0x8]
0x08048e3f <validate_name+50>: movzx eax,BYTE PTR [eax]
0x08048e42 <validate_name+53>: cmp al,0x40
0x08048e44 <validate_name+55>: jle 0x8048e53 <validate_name+70>
//if(al <= 0x40){ jmp +70 }
0x08048e46 <validate_name+57>: mov eax,DWORD PTR [ebp-0xc]
0x08048e49 <validate_name+60>: add eax,DWORD PTR [ebp+0x8]
0x08048e4c <validate_name+63>: movzx eax,BYTE PTR [eax]
0x08048e4f <validate_name+66>: cmp al,0x5a
0x08048e51 <validate_name+68>: jle 0x8048ea1 <validate_name+148>
//if(al <= 0x5a){ jmp +148 }
0x08048e53 <validate_name+70>: mov eax,DWORD PTR [ebp-0xc]
0x08048e56 <validate_name+73>: add eax,DWORD PTR [ebp+0x8]
0x08048e59 <validate_name+76>: movzx eax,BYTE PTR [eax]
0x08048e5c <validate_name+79>: cmp al,0x2f
0x08048e5e <validate_name+81>: jle 0x8048e6d <validate_name+96>
//if(al <= 0x2f){ jmp +96 }
0x08048e60 <validate_name+83>: mov eax,DWORD PTR [ebp-0xc]
0x08048e63 <validate_name+86>: add eax,DWORD PTR [ebp+0x8]
0x08048e66 <validate_name+89>: movzx eax,BYTE PTR [eax]
0x08048e69 <validate_name+92>: cmp al,0x39
0x08048e6b <validate_name+94>: jle 0x8048ea1 <validate_name+148>
//if(al <= 0x39){ jmp +148 }
0x08048e6d <validate_name+96>: mov eax,ds:0x804aea0 // stderr
0x08048e72 <validate_name+101>: mov edx,eax
0x08048e74 <validate_name+103>: mov eax,0x8049960 // background_process: incorrect name\n
0x08048e79 <validate_name+108>: mov DWORD PTR [esp+0xc],edx
0x08048e7d <validate_name+112>: mov DWORD PTR [esp+0x8],0x23
0x08048e85 <validate_name+120>: mov DWORD PTR [esp+0x4],0x1
0x08048e8d <validate_name+128>: mov DWORD PTR [esp],eax
0x08048e90 <validate_name+131>: call 0x8048c18 <fwrite@plt>
//fwrite("background_process: incorrect name\n", 0x1, 0x23, stderr)
0x08048e95 <validate_name+136>: mov DWORD PTR [esp],0x1
0x08048e9c <validate_name+143>: call 0x8048cf8 <exit@plt>
// exit(1)
0x08048ea1 <validate_name+148>: add DWORD PTR [ebp-0xc],0x1
//"net0"이면 여기로 점프함. 변수를 1로 설정함.
0x08048ea5 <validate_name+152>: mov eax,DWORD PTR [ebp-0xc]
//초기에 점프하는 곳, 변수 값을 eax에 넣어줌.
0x08048ea8 <validate_name+155>: add eax,DWORD PTR [ebp+0x8] // argv1
0x08048eab <validate_name+158>: movzx eax,BYTE PTR [eax]
//eax 초기화하고 argv1 생짜 값을 1바이트 넣음. 여기선 net0의 'n'이 들어가겠지.
0x08048eae <validate_name+161>: test al,al
0x08048eb0 <validate_name+163>: jne 0x8048e1f <validate_name+18>
0x08048eb6 <validate_name+169>: leave
0x08048eb7 <validate_name+170>: ret
분석해봐도 별거없다. 그냥 이름 잘못된건지 체크하는거임.
0x08048ecd <background_process+21>: mov BYTE PTR [ebp-0xd],0x0 //이것도 변수같은데 무튼 0
0x08048ed1 <background_process+25>: mov eax,0x8049984 // "/opt/protostar/run/%s.pid"
0x08048ed6 <background_process+30>: mov edx,DWORD PTR [ebp+0x8] // "net0"
0x08048ed9 <background_process+33>: mov DWORD PTR [esp+0xc],edx
0x08048edd <background_process+37>: mov DWORD PTR [esp+0x8],eax
0x08048ee1 <background_process+41>: mov DWORD PTR [esp+0x4],0x1ff
0x08048ee9 <background_process+49>: lea eax,[ebp-0x20c]
0x08048eef <background_process+55>: mov DWORD PTR [esp],eax
0x08048ef2 <background_process+58>: call 0x8048cd8 <snprintf@plt>
//snprintf 함수는 가령 snprintf(buffer, 100, "a is %d", 10); 식으로 사용하게되면
//a is 10이라는 문자열이 buffer에 100byte제한으로 박힘과 동시에 출력됨. 정확히는 출력먼저하고 저장할듯
//암튼 여기선 snprintf(0xbffff54c(buffer), 0x1ff, "/opt/protostar/run/%s.pid", "net0")
//0xbffff54c(ebp-0x20c)에는 /opt/protostar/run/net0.pid가 박힘
(gdb) x/10s 0xbffff54c
0xbffff54c: "/opt/protostar/run/net0.pid"
0x08048ef7 <background_process+63>: mov DWORD PTR [esp+0x8],0x1c0
0x08048eff <background_process+71>: mov DWORD PTR [esp+0x4],0x242
0x08048f07 <background_process+79>: lea eax,[ebp-0x20c]
0x08048f0d <background_process+85>: mov DWORD PTR [esp],eax
0x08048f10 <background_process+88>: call 0x8048a58 <open@plt>
//open(buffer, 0x242, 0x1c0);
0x08048f15 <background_process+93>: mov DWORD PTR [ebp-0xc],eax
0x08048f18 <background_process+96>: cmp DWORD PTR [ebp-0xc],0xffffffff
0x08048f1c <background_process+100>: jne 0x8048f5e <background_process+166>
0x08048f1e <background_process+102>: call 0x8048a38 <__errno_location@plt>
//open 함수 실패 시 -1 리턴하니까 실패했나안했나 비교함. 성공했으면 +166으로 ㄱㄱ
//실패했으면 에러번호 리턴하는 함수 호출
0x08048f23 <background_process+107>: mov eax,DWORD PTR [eax]
0x08048f25 <background_process+109>: mov DWORD PTR [esp],eax
0x08048f28 <background_process+112>: call 0x8048a88 <strerror@plt>
//에러 번호에 맞는 문자열 가져옴. 문자열포인터 리턴
0x08048f2d <background_process+117>: mov ecx,0x80499a0
//background_process: Unable to open %s, %s\n
0x08048f32 <background_process+122>: mov edx,DWORD PTR ds:0x804aea0 //stderr
0x08048f38 <background_process+128>: mov DWORD PTR [esp+0xc],eax //strerror ptr
0x08048f3c <background_process+132>: lea eax,[ebp-0x20c] //buffer
0x08048f42 <background_process+138>: mov DWORD PTR [esp+0x8],eax
0x08048f46 <background_process+142>: mov DWORD PTR [esp+0x4],ecx
0x08048f4a <background_process+146>: mov DWORD PTR [esp],edx
0x08048f4d <background_process+149>: call 0x8048c28 <fprintf@plt>
//fprintf(stderr, "background_process: Unable to open %s, %s\n", buffer, strerror ptr);
0x08048f52 <background_process+154>: mov DWORD PTR [esp],0x1
0x08048f59 <background_process+161>: call 0x8048cf8 <exit@plt>
//exit(1)
그냥 실행하니까 퍼미션없어서 실행안됨 ㅠ
background_process: Unable to open /opt/protostar/run/net0.pid, Permission denied
75 in net0/../common/common.c
//▽여기서부터 정상 호출되었을때 프로세스
0x08048f5e <background_process+166>: mov eax,DWORD PTR [ebp+0x10]
//ebp-0xc가 uid고 0x10이 gid
0x08048f61 <background_process+169>: mov DWORD PTR [ebp-0x210],eax
0x08048f67 <background_process+175>: lea eax,[ebp-0x210] //eax = &gid
0x08048f6d <background_process+181>: mov DWORD PTR [esp+0x4],eax
0x08048f71 <background_process+185>: mov DWORD PTR [esp],0x1
0x08048f78 <background_process+192>: call 0x8048a68 <setgroups@plt>
//setgroup(0x1, gid)
0x08048f7d <background_process+197>: cmp eax,0xffffffff
0x08048f80 <background_process+200>: jne 0x8048fb8 <background_process+256>
0x08048f82 <background_process+202>: call 0x8048a38 <__errno_location@plt>
0x08048f87 <background_process+207>: mov eax,DWORD PTR [eax]
0x08048f89 <background_process+209>: mov DWORD PTR [esp],eax
0x08048f8c <background_process+212>: call 0x8048a88 <strerror@plt>
0x08048f91 <background_process+217>: mov ecx,0x80499cc
0x08048f96 <background_process+222>: mov edx,DWORD PTR ds:0x804aea0
0x08048f9c <background_process+228>: mov DWORD PTR [esp+0x8],eax
0x08048fa0 <background_process+232>: mov DWORD PTR [esp+0x4],ecx
0x08048fa4 <background_process+236>: mov DWORD PTR [esp],edx
0x08048fa7 <background_process+239>: call 0x8048c28 <fprintf@plt>
0x08048fac <background_process+244>: mov DWORD PTR [esp],0xb
0x08048fb3 <background_process+251>: call 0x8048cf8 <exit@plt>
//아까랑 같은 과정. 실패하면 EPERM을 뱉어낼듯.
0x08048fb8 <background_process+256>: mov eax,DWORD PTR [ebp+0x10]
0x08048fbb <background_process+259>: mov DWORD PTR [esp+0x8],eax
0x08048fbf <background_process+263>: mov eax,DWORD PTR [ebp+0x10]
0x08048fc2 <background_process+266>: mov DWORD PTR [esp+0x4],eax
0x08048fc6 <background_process+270>: mov eax,DWORD PTR [ebp+0x10]
0x08048fc9 <background_process+273>: mov DWORD PTR [esp],eax
0x08048fcc <background_process+276>: call 0x8048b68 <setresgid@plt>
//setresgid는 그룹 권한을 재설정하는 함수임.
//int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
//setresgid(gid, gid, gid);
0x08048fd1 <background_process+281>: cmp eax,0xffffffff
0x08048fd4 <background_process+284>: jne 0x804900c <background_process+340>
//이 역시 실패시 -1 리턴
0x08048fd6 <background_process+286>: call 0x8048a38 <__errno_location@plt>
0x08048fdb <background_process+291>: mov eax,DWORD PTR [eax]
0x08048fdd <background_process+293>: mov DWORD PTR [esp],eax
0x08048fe0 <background_process+296>: call 0x8048a88 <strerror@plt>
0x08048fe5 <background_process+301>: mov ecx,0x80499fc
0x08048fea <background_process+306>: mov edx,DWORD PTR ds:0x804aea0
0x08048ff0 <background_process+312>: mov DWORD PTR [esp+0x8],eax
0x08048ff4 <background_process+316>: mov DWORD PTR [esp+0x4],ecx
0x08048ff8 <background_process+320>: mov DWORD PTR [esp],edx
0x08048ffb <background_process+323>: call 0x8048c28 <fprintf@plt>
0x08049000 <background_process+328>: mov DWORD PTR [esp],0xc
0x08049007 <background_process+335>: call 0x8048cf8 <exit@plt>
0x0804900c <background_process+340>: mov eax,DWORD PTR [ebp+0xc]
0x0804900f <background_process+343>: mov DWORD PTR [esp+0x8],eax
0x08049013 <background_process+347>: mov eax,DWORD PTR [ebp+0xc]
0x08049016 <background_process+350>: mov DWORD PTR [esp+0x4],eax
0x0804901a <background_process+354>: mov eax,DWORD PTR [ebp+0xc]
0x0804901d <background_process+357>: mov DWORD PTR [esp],eax
0x08049020 <background_process+360>: call 0x8048b58 <setresuid@plt>
//setresgid처럼 uid도 set해주는 함수이다.
//int setresuid(uid_t ruid, uid_t euid, uid_t suid);
//setresuid(uid, uid, uid);
0x08049025 <background_process+365>: cmp eax,0xffffffff
0x08049028 <background_process+368>: jne 0x8049060 <background_process+424>
0x0804902a <background_process+370>: call 0x8048a38 <__errno_location@plt>
0x0804902f <background_process+375>: mov eax,DWORD PTR [eax]
0x08049031 <background_process+377>: mov DWORD PTR [esp],eax
0x08049034 <background_process+380>: call 0x8048a88 <strerror@plt>
0x08049039 <background_process+385>: mov ecx,0x8049a2c
0x0804903e <background_process+390>: mov edx,DWORD PTR ds:0x804aea0
0x08049044 <background_process+396>: mov DWORD PTR [esp+0x8],eax
0x08049048 <background_process+400>: mov DWORD PTR [esp+0x4],ecx
0x0804904c <background_process+404>: mov DWORD PTR [esp],edx
0x0804904f <background_process+407>: call 0x8048c28 <fprintf@plt>
0x08049054 <background_process+412>: mov DWORD PTR [esp],0xd
0x0804905b <background_process+419>: call 0x8048cf8 <exit@plt>
0x08049060 <background_process+424>: mov DWORD PTR [esp+0x4],0x0
0x08049068 <background_process+432>: mov DWORD PTR [esp],0x0
0x0804906f <background_process+439>: call 0x8048a98 <daemon@plt>
//int daemon(int nochdir,int noclose);
//nochdir이 0인 경우 작업 디렉토리가 루트(/)디렉토리로 변경됩니다.
//noclose가 0인 경우 stdin, stdout, stderr이 모두 dev/null을 가리키게 됩니다.
//http://man7.org/linux/man-pages/man3/daemon.3.html
//daemon(0,0);
0x08049074 <background_process+444>: cmp eax,0xffffffff
0x08049077 <background_process+447>: jne 0x80490af <background_process+503>
//데몬만들기 성공하면 점프
0x08049079 <background_process+449>: call 0x8048a38 <__errno_location@plt>
0x0804907e <background_process+454>: mov eax,DWORD PTR [eax]
0x08049080 <background_process+456>: mov DWORD PTR [esp],eax
0x08049083 <background_process+459>: call 0x8048a88 <strerror@plt>
0x08049088 <background_process+464>: mov ecx,0x8049a5c
0x0804908d <background_process+469>: mov edx,DWORD PTR ds:0x804aea0
0x08049093 <background_process+475>: mov DWORD PTR [esp+0x8],eax
0x08049097 <background_process+479>: mov DWORD PTR [esp+0x4],ecx
0x0804909b <background_process+483>: mov DWORD PTR [esp],edx
0x0804909e <background_process+486>: call 0x8048c28 <fprintf@plt>
0x080490a3 <background_process+491>: mov DWORD PTR [esp],0x2
0x080490aa <background_process+498>: call 0x8048cf8 <exit@plt>
0x080490af <background_process+503>: call 0x8048a78 <getpid@plt>
//현재 프로세스 pid 리턴
0x080490b4 <background_process+508>: mov edx,0x8049a88 //%d
0x080490b9 <background_process+513>: mov DWORD PTR [esp+0xc],eax //pid
0x080490bd <background_process+517>: mov DWORD PTR [esp+0x8],edx //%d
0x080490c1 <background_process+521>: mov DWORD PTR [esp+0x4],0x1ff //size
0x080490c9 <background_process+529>: lea eax,[ebp-0x20c] //buffer
0x080490cf <background_process+535>: mov DWORD PTR [esp],eax
0x080490d2 <background_process+538>: call 0x8048cd8 <snprintf@plt>
//snprintf(buffer, 0x1ff, "%d", pid);
0x080490d7 <background_process+543>: lea eax,[ebp-0x20c]
0x080490dd <background_process+549>: mov DWORD PTR [esp],eax
0x080490e0 <background_process+552>: call 0x8048ba8 <strlen@plt>
//strlen(buffer);
0x080490e5 <background_process+557>: mov DWORD PTR [esp+0x8],eax //buffer length
0x080490e9 <background_process+561>: lea eax,[ebp-0x20c]
0x080490ef <background_process+567>: mov DWORD PTR [esp+0x4],eax //buffer
0x080490f3 <background_process+571>: mov eax,DWORD PTR [ebp-0xc]
0x080490f6 <background_process+574>: mov DWORD PTR [esp],eax //fd
0x080490f9 <background_process+577>: call 0x8048ae8 <write@plt>
//write(fd, buffer, strlen(buffer));
0x080490fe <background_process+582>: mov ebx,eax
0x08049100 <background_process+584>: lea eax,[ebp-0x20c]
0x08049106 <background_process+590>: mov DWORD PTR [esp],eax
0x08049109 <background_process+593>: call 0x8048ba8 <strlen@plt>
//strlen(buffer);
0x0804910e <background_process+598>: cmp ebx,eax
//아까 그 strlen값이랑 방금 한 strlen이랑 같은지 체크.
0x08049110 <background_process+600>: je 0x8049148 <background_process+656>
0x08049112 <background_process+602>: call 0x8048a38 <__errno_location@plt>
//문제없으면 656으로
0x08049117 <background_process+607>: mov eax,DWORD PTR [eax]
0x08049119 <background_process+609>: mov DWORD PTR [esp],eax
0x0804911c <background_process+612>: call 0x8048a88 <strerror@plt>
0x08049121 <background_process+617>: mov ecx,0x8049a8c
0x08049126 <background_process+622>: mov edx,DWORD PTR ds:0x804aea0
0x0804912c <background_process+628>: mov DWORD PTR [esp+0x8],eax
0x08049130 <background_process+632>: mov DWORD PTR [esp+0x4],ecx
0x08049134 <background_process+636>: mov DWORD PTR [esp],edx
0x08049137 <background_process+639>: call 0x8048c28 <fprintf@plt>
0x0804913c <background_process+644>: mov DWORD PTR [esp],0x3
0x08049143 <background_process+651>: call 0x8048cf8 <exit@plt>
0x08049148 <background_process+656>: mov eax,DWORD PTR [ebp-0xc]
0x0804914b <background_process+659>: mov DWORD PTR [esp],eax
0x0804914e <background_process+662>: call 0x8048c08 <close@plt>
//close(fd);
0x08049153 <background_process+667>: cmp eax,0xffffffff
0x08049156 <background_process+670>: jne 0x804918e <background_process+726>
//문제없으면 점프
0x08049158 <background_process+672>: call 0x8048a38 <__errno_location@plt>
0x0804915d <background_process+677>: mov eax,DWORD PTR [eax]
0x0804915f <background_process+679>: mov DWORD PTR [esp],eax
0x08049162 <background_process+682>: call 0x8048a88 <strerror@plt>
0x08049167 <background_process+687>: mov ecx,0x8049abc
0x0804916c <background_process+692>: mov edx,DWORD PTR ds:0x804aea0
0x08049172 <background_process+698>: mov DWORD PTR [esp+0x8],eax
0x08049176 <background_process+702>: mov DWORD PTR [esp+0x4],ecx
0x0804917a <background_process+706>: mov DWORD PTR [esp],edx
0x0804917d <background_process+709>: call 0x8048c28 <fprintf@plt>
0x08049182 <background_process+714>: mov DWORD PTR [esp],0x4
0x08049189 <background_process+721>: call 0x8048cf8 <exit@plt>
0x0804918e <background_process+726>: add esp,0x224
0x08049194 <background_process+732>: pop ebx
0x08049195 <background_process+733>: pop ebp
0x08049196 <background_process+734>: ret
그냥 /opt/protostar/run/net0.pid 불러와서 데몬 돌리는거임.
이제 serve_forever를 보자.
(gdb) disas serve_forever
Dump of assembler code for function serve_forever:
0x08049355 <serve_forever+0>: push ebp
0x08049356 <serve_forever+1>: mov ebp,esp
0x08049358 <serve_forever+3>: sub esp,0x38
0x0804935b <serve_forever+6>: mov eax,DWORD PTR [ebp+0x8]
0x0804935e <serve_forever+9>: mov DWORD PTR [esp],eax
0x08049361 <serve_forever+12>: call 0x8049197 <get_tcp_server_socket>
//return socket descriptor
0x08049366 <serve_forever+17>: mov DWORD PTR [ebp-0x10],eax //socket desc.
0x08049369 <serve_forever+20>: mov DWORD PTR [ebp-0x24],0x10 //변수에 0x10할당인듯
0x08049370 <serve_forever+27>: lea edx,[ebp-0x24] //edx = &(0x10)
0x08049373 <serve_forever+30>: lea ecx,[ebp-0x20]
0x08049376 <serve_forever+33>: mov eax,0x0
0x0804937b <serve_forever+38>: mov eax,ecx
0x0804937d <serve_forever+40>: mov DWORD PTR [esp+0x8],edx //addrlen
0x08049381 <serve_forever+44>: mov DWORD PTR [esp+0x4],eax //addr
0x08049385 <serve_forever+48>: mov eax,DWORD PTR [ebp-0x10]
0x08049388 <serve_forever+51>: mov DWORD PTR [esp],eax //s
0x0804938b <serve_forever+54>: call 0x8048b78 <accept@plt>
//int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
0x08049390 <serve_forever+59>: mov DWORD PTR [ebp-0xc],eax
0x08049393 <serve_forever+62>: cmp DWORD PTR [ebp-0xc],0xffffffff
0x08049397 <serve_forever+66>: jne 0x80493cf <serve_forever+122>
0x08049399 <serve_forever+68>: call 0x8048a38 <__errno_location@plt>
0x0804939e <serve_forever+73>: mov eax,DWORD PTR [eax]
0x080493a0 <serve_forever+75>: mov DWORD PTR [esp],eax
0x080493a3 <serve_forever+78>: call 0x8048a88 <strerror@plt>
0x080493a8 <serve_forever+83>: mov ecx,0x8049b8c
0x080493ad <serve_forever+88>: mov edx,DWORD PTR ds:0x804aea0
0x080493b3 <serve_forever+94>: mov DWORD PTR [esp+0x8],eax
0x080493b7 <serve_forever+98>: mov DWORD PTR [esp+0x4],ecx
0x080493bb <serve_forever+102>: mov DWORD PTR [esp],edx
0x080493be <serve_forever+105>: call 0x8048c28 <fprintf@plt>
0x080493c3 <serve_forever+110>: mov DWORD PTR [esp],0x8
0x080493ca <serve_forever+117>: call 0x8048cf8 <exit@plt>
0x080493cf <serve_forever+122>: call 0x8048c88 <fork@plt>
//새로운 자식 프로세스 생성
0x080493d4 <serve_forever+127>: cmp eax,0xffffffff
0x080493d7 <serve_forever+130>: je 0x80493df <serve_forever+138>
0x080493d9 <serve_forever+132>: test eax,eax
0x080493db <serve_forever+134>: je 0x8049415 <serve_forever+192>
0x080493dd <serve_forever+136>: jmp 0x8049425 <serve_forever+208>
0x080493df <serve_forever+138>: call 0x8048a38 <__errno_location@plt>
0x080493e4 <serve_forever+143>: mov eax,DWORD PTR [eax]
0x080493e6 <serve_forever+145>: mov DWORD PTR [esp],eax
0x080493e9 <serve_forever+148>: call 0x8048a88 <strerror@plt>
0x080493ee <serve_forever+153>: mov ecx,0x8049bb4
0x080493f3 <serve_forever+158>: mov edx,DWORD PTR ds:0x804aea0
0x080493f9 <serve_forever+164>: mov DWORD PTR [esp+0x8],eax
0x080493fd <serve_forever+168>: mov DWORD PTR [esp+0x4],ecx
0x08049401 <serve_forever+172>: mov DWORD PTR [esp],edx
0x08049404 <serve_forever+175>: call 0x8048c28 <fprintf@plt>
0x08049409 <serve_forever+180>: mov DWORD PTR [esp],0x9
0x08049410 <serve_forever+187>: call 0x8048cf8 <exit@plt>
0x08049415 <serve_forever+192>: mov eax,DWORD PTR [ebp-0x10]
0x08049418 <serve_forever+195>: mov DWORD PTR [esp],eax
0x0804941b <serve_forever+198>: call 0x8048c08 <close@plt>
0x08049420 <serve_forever+203>: mov eax,DWORD PTR [ebp-0xc]
0x08049423 <serve_forever+206>: leave
0x08049424 <serve_forever+207>: ret
0x08049425 <serve_forever+208>: mov eax,DWORD PTR [ebp-0xc]
0x08049428 <serve_forever+211>: mov DWORD PTR [esp],eax
0x0804942b <serve_forever+214>: call 0x8048c08 <close@plt>
0x08049430 <serve_forever+219>: jmp 0x8049369 <serve_forever+20>
이제 run함수
(gdb) disas run
Dump of assembler code for function run:
0x080497ba <run+0>: push ebp
0x080497bb <run+1>: mov ebp,esp
0x080497bd <run+3>: sub esp,0x28
0x080497c0 <run+6>: call 0x8048ab8 <random@plt>
0x080497c5 <run+11>: mov DWORD PTR [ebp-0xc],eax //랜덤값이 ebp-0xc에 박힘
0x080497c8 <run+14>: mov eax,0x8049c74
(gdb) x/s 0x8049c74
0x8049c74: "Please send '%d' as a little endian 32bit int\n"
0x080497cd <run+19>: mov edx,DWORD PTR [ebp-0xc]
0x080497d0 <run+22>: mov DWORD PTR [esp+0x4],edx
0x080497d4 <run+26>: mov DWORD PTR [esp],eax
0x080497d7 <run+29>: call 0x8048bc8 <printf@plt>
머 저런식으로 랜덤값 출력
0x080497dc <run+34>: mov eax,ds:0x804aea8
0x080497e1 <run+39>: mov DWORD PTR [esp+0xc],eax //버퍼인듯
0x080497e5 <run+43>: mov DWORD PTR [esp+0x8],0x1
0x080497ed <run+51>: mov DWORD PTR [esp+0x4],0x4
0x080497f5 <run+59>: lea eax,[ebp-0x10]
0x080497f8 <run+62>: mov DWORD PTR [esp],eax
0x080497fb <run+65>: call 0x8048cc8 <fread@plt>
//버퍼에서 유저인풋 읽음
0x08049800 <run+70>: test eax,eax
0x08049802 <run+72>: jne 0x8049818 <run+94>
0x08049804 <run+74>: mov DWORD PTR [esp+0x4],0x8049ca3
0x0804980c <run+82>: mov DWORD PTR [esp],0x1
0x08049813 <run+89>: call 0x8048be8 <errx@plt>
(gdb) x/s 0x8049ca3
0x8049ca3: ":(\n"
0x08049818 <run+94>: mov eax,DWORD PTR [ebp-0x10]
0x0804981b <run+97>: cmp eax,DWORD PTR [ebp-0xc]
0x0804981e <run+100>: jne 0x804982e <run+116>
0x08049820 <run+102>: mov DWORD PTR [esp],0x8049ca7
0x08049827 <run+109>: call 0x8048c78 <puts@plt>
걍 그 랜덤값이랑 비교해서 버퍼에씌인값이랑 일치하면 이거띄움
(gdb) x/s 0x8049ca7
0x8049ca7: "Thank you sir/madam"
0x0804982c <run+114>: jmp 0x8049842 <run+136>
0x0804982e <run+116>: mov edx,DWORD PTR [ebp-0x10]
0x08049831 <run+119>: mov eax,0x8049cbc
0x08049836 <run+124>: mov DWORD PTR [esp+0x4],edx
0x0804983a <run+128>: mov DWORD PTR [esp],eax
0x0804983d <run+131>: call 0x8048bc8 <printf@plt>
(gdb) x/s 0x8049cbc
0x8049cbc: "I'm sorry, you sent %d instead\n"
니가입력한건 이거임 틀렸어 출력
0x08049842 <run+136>: leave
0x08049843 <run+137>: ret
End of assembler dump.
그냥 시간나서 서브함수들 전부 분석해봤는데 정말 별거없다
외부에서 2999포트로 접근해보면 숫자를 던져주면서 리틀엔디언 32비트 int를 던져달라고한다.
근데 이 값이 계속 바뀐다.
파이썬으로 간단하게 해치우자
import socket, struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.40.141', 2999))
data = s.recv(1024)
fp = data.find("\'")+1
data = data[fp:fp+data[fp:].find("\'")]
s.send(struct.pack("<I",int(data)))
print s.recv(1024)
s.close()
C:\Users\user>E:\pwnable\protostar\net0.py
Thank you sir/madam