reverse_assembly SWITCH
29_어셈블리(switch)
- 분석 환경 : Windows7(32bit)
- 분석 도구 : OllyDbg, VS2008
1. 'switch' 구문
- 조건에 만족하면 코드를 실행하는 조건문이다.
- 대신, if 구문과 차이점은 변수 값에 따라서 다른 동작을 실시할 수 있다.
- 또한, 'break' 제어문과 같이 사용하여 조건에 만족되면 코드를 실행하고 조건 검사를 종료할 수 있다.
- switch 구문 형식은 다음과 같다.
switch (변수)
{
case 값1:
// 값이 '1'인 경우 실행하는 코드
break;
case 값2:
// 값이 '2'인 경우 실행하는 코드
break;
default:
// 위에 조건이 아닌 경우 마지막에 실행하는 코드
}
1) VS 2008을 이용하여 'switch.exe' 파일을 제작한다.
- 파일 -> 새로 만들기 -> 프로젝트 -> 빈 프로젝트 -> 위치(04_테스트) & 이름(switch) -> 확인
- '소스 파일' 우클릭 -> 추가 -> 새 항목 -> 'C++ 파일(.cpp)' 선택 -> 이름(switch) -> 추가
- 파일 -> 모두 저장 -> 닫기
2) 'cl' 명령어를 이용한 최적화 컴파일 실시
2. 'switch.exe' 파일을 'IDA Pro'를 이용하여 고급 정적 분석을 실시한다.
일단 main함수 전체의 ida-view의 모습이다.
간략하게 설명하자면,
[ebp+var_8]은 switch 로 넘겨주는 3이라는 값이 들어있다.
[ebp+var_8]을 상수값과 비교하고, 비교결과값의 결과에 따라 점프하거나. 다음상수값과 비교하여 [ebp+var_8] 와 상수값이 같아질때까지 진행하는 흐름이다.
첫 분기 직전의 모습이다. 함수 프롤로그가 수행되고 , 세번의 MOV끝에 [ebp+var_8]에는 결국 3이라는 값이 들어있다.
비교결과값이 0이 아니므로 점프하지 않고 다음 코드가 실행될것이다.
따라서 아래와 같이 빨간선을 타고 내려온 후, 2라는 숫자와 비교하게된다.
이제 3과 2를 비교할것이다.
이제 3과 3을 비교할 차례이다.
비교결과값이 0이 되므로 JZ에 의하여 401053으로 점프하게되고, 메세지박스를 실행해 ' switch구문(case 3:) ' 이라는 문구가 출력될것으로 예상된다.
이렇게 아이다로 정적분석하여 case3 으로 분기하여 'switch구문(case 3:)' 이라는 메세지박스를 실행할 것이라는 결과를 도출하였다.
이를 올리디버거로 확인해보자.
3. 올리디버거를 이용한 'switch.exe' 분석
- 메모리 주소, 레지스터 저장 값, 스택 내용, 메모리 덤프 내용, 비교 및 분기 내용 확인
1) Main함수 찾기(F8)
Main함수를 call하기 직전의 모습이다. Main함수의 주소는 401000임을 확인할 수 있다.
2) Main함수 진입(F7) – 함수 프롤로그, 함수 본체, 함수 에필로그 확인
< 함수 프롤로그 >
00401000 /$ 55 PUSH EBP
00401001 |. 8BEC MOV EBP,ESP
___________________________________________________________________________________
< 함수 본체 >
00401003 |. 83EC 08 SUB ESP,8
- 다음과 같이 지역변수 num1과 switch로 넘겨줄 파라미터를 위한 공간 4byte * 2 만큼 ESP 를 위로 올려 공간을 마련해주는 작업을 한다.
00401006 |. C745 FC 03000>MOV DWORD PTR SS:[EBP-4],3
0040100D |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
- 이 값을 위와 같이 EAX에 복사한다.
00401010 |. 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
그리고 나서 이 값을 상수와 비교하게 된다.
00401013 |. 837D F8 01 CMP DWORD PTR SS:[EBP-8],1
00401017 |. 74 0E JE SHORT switch.00401027
00401019 |. 837D F8 02 CMP DWORD PTR SS:[EBP-8],2
0040101D |. 74 1E JE SHORT switch.0040103D
- 위의 네개의 코드를 실행하면 [EBP-8]의 자리엔 3이라는 값이 들어있으므로, 비교결과값이 0이 아니므로 점프하지않고 계속 진행된다.
0040101F |. 837D F8 03 CMP DWORD PTR SS:[EBP-8],3
- 3과 [EBP-8]를 비교하면, 비교결과값은 0이 되고 ZF 는 아래와 같이 1로 변한다.
00401023 |. 74 2E JE SHORT switch.00401053
JE에 의해 아래와 같이 401053으로 점프하게된다.
< 00401053 _ case 3 >
00401053 |> \6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401055 |. 68 84814000 PUSH switch.00408184 ; |Title = "switch 구문(case 3:)"
0040105A |. 68 9C814000 PUSH switch.0040819C ; |Text = "num1 is 3"
0040105F |. 6A 00 PUSH 0 ; |hOwner = NULL
00401061 |. FF15 E8804000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
위와 같이 case 3 에 해당되는 코드들을 실행하고, 메시지박스가 실행되며 아래와 같이 " num1 is 3 " 이 출력된다.
00401067 |. EB 14 JMP SHORT switch.0040107D
- 그 후, 아래에는 default 관련 코드들이 있으므로 0040107D으로 점프하여 main함수를 종료하는 과정을 수행한다.
< 0040107D >
XOR을 통해 EAX를 0으로 초기화 시켜준 후, 함수에필로그가 수행되며 main함수는 종료된다.
00401046 |> 33C0 XOR EAX,EAX
________________________________________________________________________________________
< 함수 에필로그 >
0040107D |> \33C0 XOR EAX,EAX
0040107F |. 8BE5 MOV ESP,EBP
00401081 |. 5D POP EBP
____________________________________ main함수 소멸
00401082 \. C2 1000 RETN 10 ---> main함수 다음주소로 리턴