키젠문제이다. 시리얼이 76876-77776 일때의 name 을 찾으라한다.
총 4글자로, 마지막글자는 p 이고, 여러값이 나올수있단다
입력폼이있다. default 문자열을 확인해두자.
MFC 32bit EXE 파일이다. 올리디버거로 분석해야겠다.
글자를 입력했을때 반응하는함수이다.
0x01191740 함수에서 리턴한값으로
Correct인지 Wrong 인지 텍스트를 설정한다.
[ 0x01191740 ]
0119178E |. 50 PUSH EAX ; /Arg1 = 4
0119178F |. 81C1 30010000 ADD ECX,130 ; |
01191795 |. C645 FC 02 MOV BYTE PTR SS:[EBP-4],2 ; |
01191799 |. FF15 80321901 CALL DWORD PTR DS:[<&mfc100u.#7006>] ; \mfc100u.70FD3C63
0119179F |. 8B4D E8 MOV ECX,DWORD PTR SS:[EBP-18]
011917A2 |. 8379 F4 04 CMP DWORD PTR DS:[ECX-0C],4
011917A6 |. 74 31 JE SHORT 011917D9
첫번째관문, #7006 호출 후, 4와 비교한다. #7006 은 Getwindowtext 함수를 호출한다.
즉, name 을 가져온뒤, 길이를 4와 비교하는것이다.
011917E0 |> >56 /PUSH ESI
011917E1 |. |8D4D E8 |LEA ECX,[EBP-18]
011917E4 |. |FF15 C4321901 |CALL DWORD PTR DS:[<&mfc100u.#4478>]
011917EA |. |66:83F8 61 |CMP AX,61
011917EE |.^|72 B8 |JB SHORT 011917A8
011917F0 |. |56 |PUSH ESI
011917F1 |. |8D4D E8 |LEA ECX,[EBP-18]
011917F4 |. |FF15 C4321901 |CALL DWORD PTR DS:[<&mfc100u.#4478>]
011917FA |. |66:83F8 7A |CMP AX,7A
011917FE |.^|77 A8 |JA SHORT 011917A8
01191800 |. |46 |INC ESI
01191801 |. |83FE 04 |CMP ESI,4
01191804 |.^\7C DA \JL SHORT 011917E0
#4478 함수는 AX 에 push한 인덱스의 문자를 반환해준다. 4글자가 0x61 ~ 0x7a 범위에있어야한다.
아스키코드로 변환해보면, a~z 로 모두 소문자여야한다.
01191806 |> /33F6 /XOR ESI,ESI
01191808 |> |3BFE |/CMP EDI,ESI
0119180A |. |74 1C ||JE SHORT 01191828
0119180C |. |56 ||PUSH ESI
0119180D |. |8D4D E8 ||LEA ECX,[EBP-18]
01191810 |. |FF15 C4321901 ||CALL DWORD PTR DS:[<&mfc100u.#4478>]
01191816 |. |57 ||PUSH EDI
01191817 |. |8D4D E8 ||LEA ECX,[EBP-18]
0119181A |. |66:8BD8 ||MOV BX,AX
0119181D |. |FF15 C4321901 ||CALL DWORD PTR DS:[<&mfc100u.#4478>]
01191823 |. |66:3BC3 ||CMP AX,BX
01191826 |.^|74 80 ||JE SHORT 011917A8
01191828 |> |46 ||INC ESI
01191829 |. |83FE 04 ||CMP ESI,4
0119182C |.^|7C DA |\JL SHORT 01191808
0119182E |. |47 |INC EDI
0119182F |. |83FF 04 |CMP EDI,4
01191832 |.^\7C D2 \JL SHORT 01191806
한 문자씩가져와 나머지문자들과 비교해, 똑같은 글자가 있는지 체크한다.
0119183A |. 52 PUSH EDX ; /Arg1 = 0
0119183B |. 81C1 A4010000 ADD ECX,1A4 ; |
01191841 |. FF15 80321901 CALL DWORD PTR DS:[<&mfc100u.#7006>] ; \mfc100u.70FD3C63
01191847 |. 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
0119184A |. 8378 F4 0B CMP DWORD PTR DS:[EAX-0C],0B
0119184E |. \0F85 54FFFFFF JNE 011917A8
이번엔 serial 값을 가져와 길이가 0xB (11d) 와 같은지 체크한다.
01191854 |. 6A 05 PUSH 5
01191856 |. 8D4D EC LEA ECX,[EBP-14]
01191859 |. FF15 C4321901 CALL DWORD PTR DS:[<&mfc100u.#4478>]
0119185F |. 66:83F8 2D CMP AX,2D
01191863 |.^ 0F85 3FFFFFFF JNE 011917A8
인덱스 5, 즉 6번째글자가 '-' (0x2D) 와 같아야한다.
00DB1869 |. 6A 00 PUSH 0
00DB186B |. 8D4D E8 LEA ECX,[EBP-18]
00DB186E |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1874 |. 8AC8 MOV CL,AL
00DB1876 |. 80E1 01 AND CL,01
00DB1879 |. 884D E0 MOV BYTE PTR SS:[EBP-20],CL
00DB187C |. 8045 E0 05 ADD BYTE PTR SS:[EBP-20],5
00DB1880 |. 8AC8 MOV CL,AL
00DB1882 |. D0E9 SHR CL,1
00DB1884 |. 8AD0 MOV DL,AL
00DB1886 |. 8AD8 MOV BL,AL
00DB1888 |. 80E1 01 AND CL,01
00DB188B |. C0EA 02 SHR DL,2
00DB188E |. C0EB 03 SHR BL,3
00DB1891 |. C0E8 04 SHR AL,4
00DB1894 |. 80C1 05 ADD CL,5
00DB1897 |. 80E2 01 AND DL,01
00DB189A |. 24 01 AND AL,01
00DB189C |. 80E3 01 AND BL,01
00DB189F |. 8845 E4 MOV BYTE PTR SS:[EBP-1C],AL
00DB18A2 |. 8045 E4 05 ADD BYTE PTR SS:[EBP-1C],5
00DB18A6 |. 884D E1 MOV BYTE PTR SS:[EBP-1F],CL
00DB18A9 |. 80C2 05 ADD DL,5
00DB18AC |. 80C3 05 ADD BL,5
00DB18AF |. 6A 01 PUSH 1
00DB18B1 |. 8D4D E8 LEA ECX,[EBP-18]
00DB18B4 |. 8855 E2 MOV BYTE PTR SS:[EBP-1E],DL
00DB18B7 |. 885D E3 MOV BYTE PTR SS:[EBP-1D],BL
[EBP-0x18] = a[i] (name값) 이라고 보기쉽게 바꾸자.
[EBP-0X20] = a[0]&1+5
[EBP-0X1F] = a[0]>>1&1+5
[EBP-0X1E] = a[0]>>2&1+5
[EBP-0X1D] = a[0]>>3&1+5
[EBP-0X1C] = a[0]>>4&1+5
(연산순서는 왼쪽~오른쪽)
00DB18BA |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB18C0 |. 8AC8 MOV CL,AL
00DB18C2 |. 80E1 01 AND CL,01
00DB18C5 |. 884D D8 MOV BYTE PTR SS:[EBP-28],CL
00DB18C8 |. FE45 D8 INC BYTE PTR SS:[EBP-28]
00DB18CB |. 8AC8 MOV CL,AL
00DB18CD |. D0E9 SHR CL,1
00DB18CF |. 8AD0 MOV DL,AL
00DB18D1 |. 8AD8 MOV BL,AL
00DB18D3 |. 80E1 01 AND CL,01
00DB18D6 |. C0EA 03 SHR DL,3
00DB18D9 |. C0E8 04 SHR AL,4
00DB18DC |. 6A 0A PUSH 0A
00DB18DE |. FEC1 INC CL
00DB18E0 |. C0EB 02 SHR BL,2
00DB18E3 |. 80E2 01 AND DL,01
00DB18E6 |. 24 01 AND AL,01
00DB18E8 |. 6A 0A PUSH 0A
00DB18EA |. 8845 DC MOV BYTE PTR SS:[EBP-24],AL
00DB18ED |. FE45 DC INC BYTE PTR SS:[EBP-24]
00DB18F0 |. 884D D9 MOV BYTE PTR SS:[EBP-27],CL
00DB18F3 |. FEC2 INC DL
00DB18F5 |. 80E3 01 AND BL,01
00DB18F8 |. 6A 0A PUSH 0A
00DB18FA |. 8D4D F0 LEA ECX,[EBP-10]
00DB18FD |. FEC3 INC BL
00DB18FF |. 8855 DB MOV BYTE PTR SS:[EBP-25],DL
[EBP-0X28] = a[1]&1+1
[EBP-0X27] = a[1]>>1&1+1
BL = a[1]>>2&1+1
[EBP-0X25] = a[1]>>3&1+1
[EBP-0X24] = a[1]>>4&1+1
00DB1902 |. FF15 8432DB00 CALL DWORD PTR DS:[<&mfc100u.#4511>] ; arg1=0xA, arg2=[ebp-0x10]
00DB1908 |. 0FB655 E0 MOVZX EDX,BYTE PTR SS:[EBP-20]
00DB190C |. 8B35 B430DB00 MOV ESI,DWORD PTR DS:[<&MSVCR100._itow_s
00DB1912 |. 0FB6CB MOVZX ECX,BL
00DB1915 |. 50 PUSH EAX ; |Arg2
00DB1916 |. 03CA ADD ECX,EDX ; |
00DB1918 |. 51 PUSH ECX ; |Arg1
00DB1919 |. FFD6 CALL ESI ; \MSVCR100._itow_s
00DB191B |. 83C4 10 ADD ESP,10
00DB191E |. 6A 00 PUSH 0
00DB1920 |. 8D4D F0 LEA ECX,[EBP-10]
00DB1923 |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1929 |. 6A 00 PUSH 0
00DB192B |. 8D4D EC LEA ECX,[EBP-14]
00DB192E |. 66:8BF8 MOV DI,AX
00DB1931 |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1937 |. 8D4D F0 LEA ECX,[EBP-10]
00DB193A |. 66:3BC7 CMP AX,DI
00DB193D |.- 0F85 68FEFFFF JNE 00DB17AB
00DB1943 |. 6A FF PUSH -1 ; /Arg1 = -1
00DB1945 |. FF15 8832DB00 CALL DWORD PTR DS:[<&mfc100u.#11494>] ; \mfc100u.58ECF031
00DB194B |. 6A 0A PUSH 0A
00DB194D |. 6A 0A PUSH 0A
00DB194F |. 6A 0A PUSH 0A
00DB1951 |. 8D4D F0 LEA ECX,[EBP-10]
00DB1954 |. FF15 8432DB00 CALL DWORD PTR DS:[<&mfc100u.#4511>]
[EBP-0x14]=e[i] (serial) 으로 보기쉽게 바꾸겠다.
itow( [EBP-0x20]+BL, 0xa ) == e[0] 인 지 검사.
itow( [EBP-0x20]+BL, 0xa ) -> [EBP-0x20]+BL 을 문자로 바꾼다 ( 7 (0x7) -> '7' (0x37) )
00DB195A |. 0FB64D E3 MOVZX ECX,BYTE PTR SS:[EBP-1D]
00DB195E |. 50 PUSH EAX
00DB195F |. 0FB645 DB MOVZX EAX,BYTE PTR SS:[EBP-25]
00DB1963 |. 03C1 ADD EAX,ECX
00DB1965 |. 50 PUSH EAX
00DB1966 |. FFD6 CALL ESI
00DB1968 |. 83C4 10 ADD ESP,10
00DB196B |. 6A 01 PUSH 1
00DB196D |. 8D4D EC LEA ECX,[EBP-14]
00DB1970 |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1976 |. 6A 00 PUSH 0
00DB1978 |. 8D4D F0 LEA ECX,[EBP-10]
00DB197B |. 66:8BF8 MOV DI,AX
00DB197E |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1984 |. 8D4D F0 LEA ECX,[EBP-10]
00DB1987 |. 66:3BF8 CMP DI,AX
00DB198A |.- 0F85 1BFEFFFF JNE 00DB17AB
00DB1990 |. 6A FF PUSH -1 ; /Arg1 = -1
00DB1992 |. FF15 8832DB00 CALL DWORD PTR DS:[<&mfc100u.#11494>] ; \mfc100u.58ECF031
00DB1998 |. 6A 0A PUSH 0A
00DB199A |. 6A 0A PUSH 0A
00DB199C |. 6A 0A PUSH 0A
00DB199E |. 8D4D F0 LEA ECX,[EBP-10]
00DB19A1 |. FF15 8432DB00 CALL DWORD PTR DS:[<&mfc100u.#4511>]
위에있는 로직과 같은모양을가지고있다.
e[1]==[EBP-0X25] + [EBP-0X1D]) 인 지 검사
00DB19A7 |. 0FB655 DC MOVZX EDX,BYTE PTR SS:[EBP-24]
00DB19AB |. 50 PUSH EAX
00DB19AC |. 0FB645 E1 MOVZX EAX,BYTE PTR SS:[EBP-1F]
00DB19B0 |. 03D0 ADD EDX,EAX
00DB19B2 |. 52 PUSH EDX
00DB19B3 |. FFD6 CALL ESI
00DB19B5 |. 83C4 10 ADD ESP,10
00DB19B8 |. 6A 02 PUSH 2
00DB19BA |. 8D4D EC LEA ECX,[EBP-14]
00DB19BD |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB19C3 |. 6A 00 PUSH 0
00DB19C5 |. 8D4D F0 LEA ECX,[EBP-10]
00DB19C8 |. 66:8BF8 MOV DI,AX
00DB19CB |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB19D1 |. 8D4D F0 LEA ECX,[EBP-10]
00DB19D4 |. 66:3BF8 CMP DI,AX
00DB19D7 |.- 0F85 CEFDFFFF JNE 00DB17AB
00DB19DD |. 6A FF PUSH -1 ; /Arg1 = -1
00DB19DF |. FF15 8832DB00 CALL DWORD PTR DS:[<&mfc100u.#11494>] ; \mfc100u.58ECF031
00DB19E5 |. 6A 0A PUSH 0A
00DB19E7 |. 6A 0A PUSH 0A
00DB19E9 |. 6A 0A PUSH 0A
00DB19EB |. 8D4D F0 LEA ECX,[EBP-10]
00DB19EE |. FF15 8432DB00 CALL DWORD PTR DS:[<&mfc100u.#4511>]
e[2]==[EBP-0X24]+[EBP-0X1F] 인 지 검사
00DB19F4 |. 0FB655 E2 MOVZX EDX,BYTE PTR SS:[EBP-1E]
00DB19F8 |. 0FB64D D8 MOVZX ECX,BYTE PTR SS:[EBP-28]
00DB19FC |. 50 PUSH EAX
00DB19FD |. 03CA ADD ECX,EDX
00DB19FF |. 51 PUSH ECX
00DB1A00 |. FFD6 CALL ESI
00DB1A02 |. 83C4 10 ADD ESP,10
00DB1A05 |. 6A 03 PUSH 3
00DB1A07 |. 8D4D EC LEA ECX,[EBP-14]
00DB1A0A |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1A10 |. 6A 00 PUSH 0
00DB1A12 |. 8D4D F0 LEA ECX,[EBP-10]
00DB1A15 |. 66:8BF8 MOV DI,AX
00DB1A18 |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1A1E |. 8D4D F0 LEA ECX,[EBP-10]
00DB1A21 |. 66:3BF8 CMP DI,AX
00DB1A24 |.- 0F85 81FDFFFF JNE 00DB17AB
00DB1A2A |. 6A FF PUSH -1 ; /Arg1 = -1
00DB1A2C |. FF15 8832DB00 CALL DWORD PTR DS:[<&mfc100u.#11494>] ; \mfc100u.58ECF031
00DB1A32 |. 6A 0A PUSH 0A
00DB1A34 |. 6A 0A PUSH 0A
00DB1A36 |. 6A 0A PUSH 0A
00DB1A38 |. 8D4D F0 LEA ECX,[EBP-10]
00DB1A3B |. FF15 8432DB00 CALL DWORD PTR DS:[<&mfc100u.#4511>]
e[3]=[EBP-0X1E]+[EBP-0X28] 인 지 검사
00DB1A41 |. 0FB64D E4 MOVZX ECX,BYTE PTR SS:[EBP-1C]
00DB1A45 |. 50 PUSH EAX
00DB1A46 |. 0FB645 D9 MOVZX EAX,BYTE PTR SS:[EBP-27]
00DB1A4A |. 03C1 ADD EAX,ECX
00DB1A4C |. 50 PUSH EAX
00DB1A4D |. FFD6 CALL ESI
00DB1A4F |. 83C4 10 ADD ESP,10
00DB1A52 |. 6A 04 PUSH 4
00DB1A54 |. 8D4D EC LEA ECX,[EBP-14]
00DB1A57 |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1A5D |. 6A 00 PUSH 0
00DB1A5F |. 8D4D F0 LEA ECX,[EBP-10]
00DB1A62 |. 66:8BF8 MOV DI,AX
00DB1A65 |. FF15 C432DB00 CALL DWORD PTR DS:[<&mfc100u.#4478>]
00DB1A6B |. 8D4D F0 LEA ECX,[EBP-10]
00DB1A6E |. 66:3BF8 CMP DI,AX
00DB1A71 |.- 0F85 34FDFFFF JNE 00DB17AB
00DB1A77 |. 6A FF PUSH -1 ; /Arg1 = -1
00DB1A79 |. FF15 8832DB00 CALL DWORD PTR DS:[<&mfc100u.#11494>] ; \mfc100u.58ECF031
e[4]==[EBP-0X1C]+[EBP-0X27] 인 지 검사
a[2], a[3] 도 똑같은방식으로 serial 을 만든다.
시리얼만드는방식을 코드로 옮겨서, 76876-77776 이 되는 4글자를 브루트포스로 찾으면되겠다.
[ c ]
#include<stdio.h>
int main(void) {
int v20,v1f,v1e,v1d,v1c,v28,v27,bl,v25,v24,i,j;
for(i=0x61;i<=0x7a;i++){
for(j=0x61;j<=0x7a;j++){
v20=(i&1)+5;
v1f=(i>>1&1)+5;
v1e=(i>>2&1)+5;
v1d=(i>>3&1)+5;
v1c=(i>>4&1)+5;
v28=(j&1)+1;
v27=(j>>1&1)+1;
bl=(j>>2&1)+1;
v25=(j>>3&1)+1;
v24=(j>>4&1)+1;
if(v20+bl==7)
if(v25+v1d==6)
if(v24+v1f==8)
if(v28+v1e==7)
if(v27+v1c==6)
printf("%c,%c\n",i,j);
}
}
for(i=0x61;i<=0x7a;i++){
int p=0x70; //마지막글자는 p
v20=(i&1)+5;
v1f=(i>>1&1)+5;
v1e=(i>>2&1)+5;
v1d=(i>>3&1)+5;
v1c=(i>>4&1)+5;
v28=(p&1)+1;
v27=(p>>1&1)+1;
bl=(p>>2&1)+1;
v25=(p>>3&1)+1;
v24=(p>>4&1)+1;
if(v20+bl==7)
if(v25+v1d==7)
if(v24+v1f==7)
if(v28+v1e==7)
if(v27+v1c==6)
printf("%c,%c\n",i,p);
}
}
연산은 2글자씩 가져와서 하기때문에, 2중반복문 2개를 만들어서,
76876 을 만족하는 2글자, 77776 을 만족하는 두글자를 각각 출력했다. (마지막글자는 p)
만들수 있는 4글자는,
bugp
bump
cqgp
cqmp
ftgp
ftmp
총 6개가있다.
6개중에 하나일것이다.