ssongk
ssongk
ssongk
전체 방문자
오늘
어제

공지사항

  • resources
  • 분류 전체보기 (626)
    • CTF (24)
    • background (79)
      • fuzzing (5)
      • linux (29)
      • linux kernel (15)
      • windows (2)
      • web assembly (1)
      • embedded (0)
      • web (13)
      • crypto (9)
      • mobile (1)
      • AI (1)
      • etc.. (3)
    • write-up(pwn) (171)
      • dreamhack (102)
      • pwn.college (4)
      • pwnable.xyz (51)
      • pwnable.tw (3)
      • pwnable.kr (5)
      • G04T (6)
    • write-up(rev) (32)
      • dreamhack (24)
      • reversing.kr (8)
    • write-up(web) (195)
      • dreamhack (63)
      • LOS (40)
      • webhacking.kr (69)
      • websec.fr (3)
      • wargame.kr (6)
      • webgoat (1)
      • G04T (7)
      • suninatas (6)
    • write-up(crypto) (19)
      • dreamhack (16)
      • G04T (1)
      • suninatas (2)
    • write-up(forensic) (53)
      • dreamhack (5)
      • ctf-d (47)
      • suninatas (1)
    • write-up(misc) (13)
      • dreamhack (12)
      • suninatas (1)
    • development (31)
      • Linux (14)
      • Java (13)
      • Python (1)
      • C (2)
      • TroubleShooting (1)
    • 자격증 (8)
    • 이산수학 (1)
    • 정보보안 (0)
hELLO · Designed By 정상우.
ssongk

ssongk

[reversing.kr] Replace write-up
write-up(rev)/reversing.kr

[reversing.kr] Replace write-up

2024. 6. 1. 01:33

일반적인 리버싱 문제의 형태인 입력 값 검증 문제다.

하지만 값을 입력하면 종료된다.

 

원인을 찾기 위해 ida와 xdbg로 분석한다.

WinMain은 단순하다.

콜백 함수인 DialogFunc만 보면 된다.

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  DialogBoxParamA(hInstance, (LPCSTR)0x65, 0, DialogFunc, 0);
  return 0;
}

 

check 버튼을 누르면 a3 == 0x3EB을 만족하게 된다.

0x3EA에는 입력한 값이 있으며, GetDlgItemInt 함수로 가져올 수 있다.

즉, dword_4084D0에 입력 값이 저장된다.

(0x3EA, 0x3EB는 다이얼로그 박스의 id 값으로 활용된다)

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  if ( a2 != 0x111 )
    return 0;
  if ( (unsigned __int16)a3 == 2 )
  {
    EndDialog(hDlg, 2);
    return 1;
  }
  else if ( (unsigned __int16)a3 == 0x3EB )
  {
    dword_4084D0 = GetDlgItemInt(hDlg, 0x3EA, 0, 0);
    sub_40466F();
    sub_404689(&loc_40469F);
    *(_DWORD *)sub_40466F = 0xC39000C6;
    sub_40466F();
    sub_40466F();
    *(_DWORD *)sub_40466F = 0x6E8;
    return 1;
  }
  else
  {
    return 0;
  }
}

 

이제부턴 어셈으로 보는 것이 좋다.

(디버거를 활용해도 좋음)

 

GetDlgItemInt 함수 호출 이후부터 살펴보면 된다.

0x40466F를 호출한 뒤 0x404690으로 점프한다.

.text:0040105A                 call    ds:GetDlgItemInt
.text:00401060                 mov     dword_4084D0, eax
.text:00401065                 call    sub_40466F
.text:0040106A                 xor     eax, eax
.text:0040106C                 jmp     loc_404690

 

0x40466F을 보면 opcode가 다 해석되지 않고 깨져있다.

단축키 'c'를 통해 해결할 수 있다.

0x40467A를 호출한 뒤, 0x404689를 호출한다.

.text:0040466F ; int sub_40466F(void)
.text:0040466F sub_40466F      proc near               ; CODE XREF: DialogFunc+45↑p
.text:0040466F                                         ; DialogFunc+3689↓p ...
.text:0040466F                 call    loc_40467A
.text:0040466F ; ---------------------------------------------------------------------------
.text:00404674                 dd 84D00581h
.text:00404678                 db 40h, 0
.text:0040467A ; ---------------------------------------------------------------------------
.text:0040467A
.text:0040467A loc_40467A:                             ; CODE XREF: sub_40466F↑j
.text:0040467A                 mov     dword_406014+2, 619060EBh
.text:00404684                 call    $+5
.text:00404684 sub_40466F      endp ; sp-analysis failed

 

0x404674를 클릭한 뒤 'c'를 누르면 다음과 같이 바뀐다.

입력 값이 저장된 0x4084D0에 +0x601605C7을 수행한다.

.text:0040466F sub_40466F      proc near               ; CODE XREF: DialogFunc+45↑p
.text:0040466F                                         ; DialogFunc+3689↓p ...
.text:0040466F                 call    near ptr loc_404674+6
.text:00404674
.text:00404674 loc_404674:                             ; CODE XREF: sub_40466F↑p
.text:00404674                 add     dword_4084D0, 601605C7h
.text:0040467E                 inc     eax
.text:0040467F                 add     bl, ch
.text:00404681                 pusha
.text:00404682                 nop
.text:00404683                 popa
.text:00404684                 call    $+5
.text:00404684 sub_40466F      endp

 

0x404689에선 입력 값이 저장된 0x4084D0에 +1을 수행한다.

.text:00404689 ; int __cdecl sub_404689(_DWORD)
.text:00404689 sub_404689      proc near               ; CODE XREF: DialogFunc+367A↓p
.text:00404689                 inc     dword_4084D0
.text:0040468F                 retn
.text:0040468F sub_404689      endp

 

이제 0x40466F를 호출한 뒤 점프하는 0x404690을 분석한다.

입력 값이 저장된 0x4084D0를 eax에 저장하고 0x404689를 호출한다.

(0x4084D0에 +1이 된다)

 

이후 0x40466F를 여러 번 호출하는데

mov를 사용해서 opcode를 수정하는 루틴이 있다.

(중간에 0x4084D0에 +1하는 부분도 있다)

 

마지막에 0x401071로 점프한다.

.text:00404690 ; START OF FUNCTION CHUNK FOR DialogFunc
.text:00404690
.text:00404690 loc_404690:                             ; CODE XREF: DialogFunc+4C↑j
.text:00404690                 mov     eax, dword_4084D0
.text:00404695                 push    offset loc_40469F
.text:0040469A                 call    sub_404689
.text:0040469F
.text:0040469F loc_40469F:                             ; DATA XREF: DialogFunc+3675↑o
.text:0040469F                 mov     dword ptr ds:sub_40466F, 0C39000C6h
.text:004046A9                 call    sub_40466F
.text:004046AE                 inc     eax
.text:004046AF                 call    sub_40466F
.text:004046B4                 mov     dword ptr ds:sub_40466F, 6E8h
.text:004046BE                 pop     eax
.text:004046BF                 mov     eax, 0FFFFFFFFh
.text:004046C4                 jmp     loc_401071
.text:004046C4 ; END OF FUNCTION CHUNK FOR DialogFunc

 

0x40469F에선 다음과 같이 바뀐다.

c6 00 90                mov    BYTE PTR [eax],0x90
3c                      ret

 

이후 0x4046B4에서 다시 원래대로 돌린다.

E8 06 00 00 00          call    near ptr loc_404674+6

 

마지막 점프하는 0x401071은 다음과 같다.

"Correct!"를 출력해줘야 하는데 0x401084로 점프해서 끝나버린다.

.text:00401071 loc_401071:                             ; CODE XREF: DialogFunc+36A4↓j
.text:00401071                 jmp     short loc_401084
.text:00401073 ; ---------------------------------------------------------------------------
.text:00401073                 push    offset String   ; "Correct!"
.text:00401078                 push    3E9h            ; nIDDlgItem
.text:0040107D                 push    esi             ; hDlg
.text:0040107E                 call    ds:SetDlgItemTextA
.text:00401084
.text:00401084 loc_401084:                             ; CODE XREF: DialogFunc:loc_401071↑j
.text:00401084                 mov     eax, 1
.text:00401089                 nop
.text:0040108A                 nop
.text:0040108B                 nop
.text:0040108C                 nop
.text:0040108D                 nop
.text:0040108E                 nop
.text:0040108F                 nop
.text:00401090                 pop     esi
.text:00401091                 pop     ebp
.text:00401092                 retn    10h

 

0x40469F에서 바뀌는 opcode를 이용해서

EB 11을 90 90으로 바꿔주면 되겠다.

c6 00 90                mov    BYTE PTR [eax],0x90
3c                      .byte 0x3c
.text:00401071 EB 11                                   jmp     short loc_401084

 

디버깅 해보면 dword_4084D0은 다음 식을 만족해야 한다.

dword_4084D0 + 0x601605C7 + 1*4 = 0x401071

 

계산 결과인 2687109798을 입력하면 Correct!가 출력된다.

'write-up(rev) > reversing.kr' 카테고리의 다른 글

[reversing.kr] Position write-up  (1) 2024.06.15
[reversing.kr] ImagePrc write-up  (2) 2024.06.06
[reversing.kr] Music Player write-up  (0) 2024.05.31
[reversing.kr] Easy ELF write-up  (0) 2023.08.30
[reversing.kr] Easy Unpack write-up  (0) 2023.08.30
    'write-up(rev)/reversing.kr' 카테고리의 다른 글
    • [reversing.kr] Position write-up
    • [reversing.kr] ImagePrc write-up
    • [reversing.kr] Music Player write-up
    • [reversing.kr] Easy ELF write-up
    ssongk
    ssongk
    벌레 사냥꾼이 되고 싶어요

    티스토리툴바