ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CodeEngn Basic RCE 14
    $ 리버싱 $/CodeEngn Basic RCE 2019. 5. 7. 16:06

    해당 문제에서 Name과 Serial을 입력하는 폼이 있는것 같습니다. 

    한번 파일을 확인해 보겠습니다.

     

    UPX로 Packing 되어 있는 파일입니다. 

     

    해당 파일을 UPX.exe 파일로 Unpacking을 해보겠습니다.

     

    Unpacking 한 후의 파일을 확인해 보면 다음과 같습니다.

     

    올리디버거로 열어 보겠습니다. 

     

    이런 모습의 코드가 나옵니다. 

     

    일단 함수를 확인해서 입력받는 함수를 찾아 보겠습니다. 

     

    GetDlgItem 관련 함수를 전부 BP걸어 보았습니다. 

    F9를 이용해서 이동해 보겠습니다.

     

    4번정도 누르니까 입력을 받기 위해서 대기를 합니다. 

    Name에 CodeEngn , Serial에 1234를 입력해 보겠습니다.

     

    그러면 004012BD에서 멈춰 있습니다. 

     

    4012C2부터 코드를 해석해 보도록 하겠습니다.

     

    004012B1

    PUSH 40

    Count 40

    004012B3

    PUSH 14.00403038

    Buffer (사용자가 입력한 값을 403038에 저장)

    004012B8

    PUSH 6A

    Control ID

    004012BA

    PUSH DWORD PTR SS:[EBP+8]

    hWnd

    004012BD

    CALL <JMP.&USER32.GetDlgItemTextA>

    GetDlgItemTextA 함수 호출 (Name 입력 Form)

    004012C2

    CMP EAX, 0

    EAX (Name 의 글자수) 와 0 비교

    004012C5

    JE SHORT 14.004012DF

    EAX 가 0 (Name Form에 아무것도 적지 않았을때) 이면 4012DF로 이동

    004012C7

    PUSH 40

    Count 40

    004012C9

    PUSH 14.00403138

    Buffer (사용자가 입력한 값을 403138에 저장)

    004012CE

    PUSH 6B

    Control ID

    004012D0

    PUSH DWORD PTR SS:[EBP+8]

    hWnd

    004012D3

    CALL <JMP.&USER32.GetDlgItemTextA>

    GetDlgItemTextA 함수 호출 (Serial 입력 Form)

    004012D8

    CMP EAX, 0

    EAX (Serial 의 글자수) 와 0 비교

    004012DB

    JE SHORT 14.004012DF

    EAX 가 0 (Serial Form에 아무것도 적지 않았을때) 이면 4012DF로 이동

    004012DD

    JMP SHORT 14.004012F6

    4012F6으로 점프

    004012DF

    PUSH 0

    Style

    004012E1

    PUSH 14.00403462

    Title

    004012E6

    PUSH 14.00403000

    Text

    004012EB

    PUSH 0

    hOwner

    004012ED

    CALL <JMP.&USER32.MessageBoxA>

    MessageBoxA 함수 (입력값이 없으면 출력하는 메시지)

     

    이를 지나면 엄청나게 중요한 알고리즘이 나타납니다.

     

    해당 알고리즘에 대해서 설명을 해보겠습니다.

     

    간략하게 설명하자면 name의 길이를 구하기 -> 길이 만큼 알고리즘을 반복시키기 -> 해강 결과를 ESI에 저장 ->serial 값을 16진수로 변환후 EAX에 저장 -> EAX와 ESI를  비교 -> 분기 의 형식이 됩니다.

     

     

    004012F6

    PUSH 14.00403038

    name 값 (CodeEngn)

    004012F8

    CALL <JMP.&KERNEL32.lstrlenA>

    lstrlen 함수 호출 길이 값 EAX에 저장

    00401300

    XOR ESI, ESI

    ESI 0 으로 초기화

    00401302

    MOV ECX, EAX

    ECX에 EAX 값 저장

    00401304

    MOV EAX, 1

    EAX 값에 1 저장

    00401309

    MOV EDX, DWORD PTR DS:[403038]

    EDX에 첫번째 부터 4번째 문자열 저장

    0040130F

    MOV DL, BYTE PTR DS:[EAX+403037]

    DL에 첫 문자열 저장

    00401315

    AND EDX, 0FF

    EDX에 0FF를 AND연산 해서 EDX에 DL이 남도록 함

    0040131B

    MOV EBX, EDX

    EDX값을 EBX에 저장

    0040131D

    IMUL EBX, EDX

    EBX와 EDX 값을 곱한다. 그리고 다시 EBX에 저장.

    00401320

    ADD ESI, EBX

    ESI값에 EBX(제 곱값)를 더한다.

    00401322

    MOV EBX, EDX

    EDX의 값을 EBX에 저장

    00401324

    SAR EBX, 1

    쉬프트 연산자 진행 (S: 쉬프트 , A:산술 , R:우측)

    00401326

    ADD ESI, EBX

    ESI에 EBX값을 더하기

    00401328

    SUB ESI, EDX

    ESI에 EDX값 빼기

    0040132A

    INC EAX

    EAX에 1 증가

    0040132B

    DEC ECX

    ECX에 1 감소

    0040132C

    JNZ SHORT 14.00401309

    ECX값이 0 이면 점프

    0040132E

    PUSH ESI

    ESI값 PUSH

    0040132F

    PUSH 14.00403138

    입력한 Serial 값 PUSH

    00401334

    CALL 14.00401383

    16진수로 변환하는 코드 호출

    00401339

    POP ESI

    ESI값을 POP

    0040133A

    CMP EAX, ESI

    EAX와 ESI 비교

    0040133C

    JNZ SHORT 14.00401353

    같으면 분기

    위처럼 알고리즘이 반복합니다.

     

    그렇게 하고 40133A 주소에 도착하면 다음과 같은 문자열을 확인 할 수 있습니다.

    EAX는 제가 입력한 1234가 16진수로 들어간 것이므로 

    진짜 Serial은 129A1 입니다 이를 10진수로 변환 하면 다음과 같습니다.

    129A1 = 76193

     

    Serial 값은 76193입니다.

     

     

     

    '$ 리버싱 $ > CodeEngn Basic RCE' 카테고리의 다른 글

    CodeEngn Basic RCE 16  (0) 2019.05.07
    CodeEngn Basic RCE 15  (0) 2019.05.07
    CodeEngn Basic RCE 13  (0) 2019.05.06
    CodeEngn Basic RCE 12  (0) 2019.05.06
    CodeEngn Basic RCE 11  (0) 2019.05.06

    댓글

Designed by Tistory.