winmain을 어셈블리어에서 구별하는법

GetModuleHandle 밑에 CALL이 winmain이다.

 

1. 소스

 

2. 어셈블리어

MessageBOX부터 위로 코딩을 하면 된다.

 

 

 

퀴즈3.exe 파일의 코드 찾아내기

정답:

 

 

퀴즈4.exe 파일의 코드 찾아내기

 

 

 

MOV DWORD PTR SS:[EBP-A],EDX   //EDX의값 즉 공간을 다쓰고 6바이트가 남아서 6바이트를 0으로채움

MOV WORD PTR SS:[EBP-6],DX   // char str[24] = "AegisOne Security"; 

LEA EAX,DWORD PTR SS:[EBP-1C]  // EBP-1C는 배열의 첫주소이므로 배열명이 된다 따라서 str

MOV DWORD PTR SS:[EBP-4],EAX  // char * p = str;

 

 

MOVSX EDX,BYTE PTR DS:[ECX+6]   // 현재 ECX는 p이므로 p+6의 값을 저장     =*(p+6);

MOV DWORD PTR SS:[EBP-20],EDX   // int  n = *(p+6);

 

 

정답 :

 

 

 

퀴즈5

 

함수 파라미터들이 고정인 함수들이다.

strcpy(1,2);

memcpy(1,2,3);

strcmp(1,2);

strlen(1);

malloc(1);

free(1);

sprintf를 나타내고 있다. 총 24바이트중 int형인 4바이트만 사용 했으므로, 배열에 남은 20바이트를 지정한다.

PUSH가 3개인 것으로 보아, 값이 3개임을 알 수 있다.

func(&x, "%d", n);           이 형태를 보아 sprintf임이 유추가된다.

 

sprintf의 기본 양식은

sprintf(string, "%d", n ); 이다.

MOV DWORD PTR SS:[EBP-18],5    // int n = 5;

 

LEA EDX,DWORD PTR SS:[EBP-14] //배열의 시작주소를 나타낸다.

 

 

 

정답

 

 

 

퀴즈06

값 변경하기

 

이 값을 10으로 변경
저부분의 값을 변경하면 된다.
Selection 1개만 변경시 사용 

Selection 1개만 수정했을 시 사용

All modifications 여러개 수정했을 시 사용

 

수정한 후 copy all -> seve로 exe파일을 저장하면 완전히 수정이 된다.

 

 

값이 변한 것을 확인

 

소스분석

함수 첫 부분

PUSH

PUSH

PUSH

CALL 구조를 보아 sprint임을 유추

 

 

따라서 00401006의 값을 변경하면 값이 변한다.

 

 

 

 

조건문

 

 

조건문(if)

 

CMP 피연산자1 , 피연산자2  //1~2를 하여 양수, 음수,0을 판단 

 

CMP 피연산자1 에서 피연산자2를 빼고 양수면 피연산자1이 크고 음수면 피연산자2,  0이면 같다.

 

JE 같으면  JMP 가실행 

JNZ 서로 다르면 JMP가실행 

 

 

JGE 왼쪽이 크거나 같으면  JMP가 실행

JLE 왼쪽이 작거나 같으면  JMP가 실행

 

if(n<= 10)

JG 왼쪽이 크면 실행

 

if(n <= 10)

JL 왼쪽이 작으면 실행

 

 

 

 

 

if문이 참이되어 실행되면 JMP명령을통해 else부분을 뛰어넘긴다.

 

JMP문을 통해 0040103B로 온다.

 

 

 

 

 

 

and 연산자

 

 

 

 

or연산자

 

or연산자이기 때문에 그대로 연산자가 된다.

and와 다르게 jge가 참이면 push0 부분 즉 , 종속문장을 실행한다.

 

 

문제 02-1

 

아래 어셈블리어의 맞는 코드 작성

 

 

 

정답:

 

 

 

 

 

퀴즈 02-2

 

 

분석

 

MOV EAX,DWORD PTR SS:[EBP+10]  //arg 3   == lpCmdLine

EBP + 8   //arg 1

EBP + C   //arg 2

EBP + 10   //arg 3

 

따라서 lpCmdLine을 불러오면 된다.

 

Arg를 PUSH하고 들어갔으므로, EBP + * 은 arg를 의미

 

 

 

 CDQ는 나눗셈을 의미한다.  IDIV  몫과 나눗셈을 한번에 구한다.
TEST를 통해 EAX를 사용하고, EDX의 값은 MOVSX를 통해 다른 데이터로 덮어졌으므로, 몫의 값만 사용된 것을 알 수 있다.

TEST  참거짓을 비교하는 비교 연산자.

위의 문장을 통해 IDIV ECX의 값이 ch /13이 됨을 알 수 있다.

 

if의 종속문장 
else의 종속문장

 

JE  조건식 점프로 뛰는 범위 안에 JNZ가 겹쳐있으므로 or임을 유추한다.

JNZ는 앞에 문장이 참일 시 건너뛰는 용도로 사용되기 때문에 반대로 생각해야된다.

 

 

위의 어셈블에 대한 소스 정답.

0x49 - 0x34 + 0x41 = 0x56     0x56 == 'V'  즉 , 3번째 문자열에 V가 오는 값을 아규먼트로 등록해주면 success가 뜬다.

 

 

 

 

Switch case 문 유형 1.

 

 

위의 소스 어셈블리어

소스분석

2문장이 switch(n)을 의미 

 

case 0 , case1 , default를 의미 
위의 문장 JE에서 시작부분이 00401021로 가라 나타냈기 때문에 case0에 해당하는 문장임을 알 수 있다.

 

JE부분이 00401037로 가라 나타냈기 때문에 case1부분이다. JMP는 소스에서 break를 의미하기 때문에 전부 같은 주소를 가리킨다.

같은주소 == switch문의 끝

JMP부분이 0040104D로 가라했기 때문에 default부분이다.

 

 

스위치문은 이런형태로 나온다.

 

 

Switch case 문 유형 2.

Switch문이 4개 이상일 경우

어셈블리어 소스

 

소스 분석

4개이상의 case가 나올 시 위와 같이 단축되어 나온다. JA는 JG와 동일
default 부분이다. 즉 case의 마지막번호랑 비교해서 크다면 default로 가게 한다.
case부분이다. ECX*4는 고정, 뒤에 주소는 변함. 

즉 상수가 0일 경우  0*4 + 401097     //16진수계산

case 0 : 401097    

case 1 : 40109B

case 2 : 40109F

case 3 : 4010A3

 

위의 주소에 위치하는 데이터값의 번호에 관련된 곳에 case 시작부분이 있다.

 

 

퀴즈 2-3

소스분석

 

EBP+10 이므로 아규먼트 3번째값 lpCmdLine임을 알 수 있고,  JNZ이므로 0이 아니면 점프한다는 의미이기에 if(*lpCmdLine==0)이 된다.

 

if의 참인 부분 JNZ의 주소가 00401029를 가르키므로 그 전에 주소는 if문의 값이 된다.

OR EAX,FFFFFFFF  //  MOV EAX , -1 을 의미 

JMP의 주소가 함수 마지막을 가르키므로 return이 된다.

 

lpCmdLine[0] - 0x30은 값이 정수로 나올수 밖에 없으므로 int형이다.

 

n과 5를 XOR연산

 

 

CMP JE CMP JE 순을보아 Switch문임을 유추

 

case2 와 case4의 내용  JMP는 break;

 

default의 내용 

 

 

소스로 변환한 정답 

 

소스를 수정해서 success를 띄우는법

n^5 -> 4가 되는 값은 n == 1이다.

문자 '0'은 16진수로 0x30  10진수로 48이다. 따라서, lpCmdLine[0]의 값이 1이면 success가 출력된다.

 

 

 

 

2-4 퀴즈

 

어셈블리어

 

 

분석

MOV DWORD PTR SS:[EBP-4],EAX 문장을 통해  x라는 변수에 func(lpCmdLine)을 넣는다.

 

밑에 문장을 보아 switch(x)을 의미

 

case3개를 가진 switch문

40109F주소의 헥사값을 보면 저기에 적힌 주소들이 case문의 내용이다.

 

push가 1개인 것으로 보아, 인자가 1개인 함수이다. 

이제 여기서 추리를 한다.   lpCmdLine이니까 arument에 값을 하나한씩 넣어보면서 규칙을 찾아낸다.

 

1234를 넣어본다.
4라는 값이 반환 되었다.

 

123456을 입력해보았다.
6이라는 값이 반환되었다.

위의 규칙을 통해 문자열의 길이를 파악한다는 것을 알 수있다. 따라서 strlen()함수이다.

 

소스 정답

 

따라서 success를 띄우기 위해서는 x의 값이 4이상 이면 된다.

 

for문

벗어나는 키 F4

 

위의 소스에 관련된 어셈블리어

분석

이 형태면 무조건 for문이라 생각한다.

초기식 -> JMP하는 내용이 증감식이다.  for(i=1; ; i++)

JMP로 도착한 부분부터 다음 JMP까지가 조건식이다. for(i=1; i <11(0B); i++)

다음 JMP하는 내용이 종속문장이다.   sum = sum + i;  

위로 다시 올라간다. for문계속실행하는 JMP

분석해보면 아래와 같은 for문이 나온다.

for(i=1; i<11; i++)   
sum+=i;  

 

 

 

for 2번째 유형

 

어셈블리어

분석

char str[]="string";

for문의 형태이다.

 

MOV 

ADD

MOV 를통해  len++임을 알고

*(str+len) == str[len]

MOVSX 에서 EBP-8 + ECX인데, MOV연산자이기 때문에 안에 값을 가져온다 따라서 *(str+len)이된다.

JE기 때문에  *(str+len) 그대로 연산식이 된다.

JE와 JMP 사이에 값이 없으므로 안에 종속문장은 없다.

 

 

 

 

while문

 

 

 

if문이랑 비슷한데, 젤 마지막 JMP가 JMP했을 때 위로 올라가면 while 아래로 내려가면 else로 생각

 

continue는 종속문장 안에서 나온다. 

break                                           둘다 jmp로 나오니 혼동x

 

분석

 

 

2-5 퀴즈

 

소스정답

 

2-6 퀴즈

 

정답:

 

 

 

 

2-7

어셈코드

 

 

분석.

for문에 관련된 문장
while의 내용
아래 마지막 sucess문장

 

정답

 

success 띄우기

atoi()함수가 하는일 즉, 문자열 "123" 을 정수형 123으로 변환하는 코드이다.

즉 , 이 소스는 리버싱을 어렵게하기위해 0x30을 -> 0x2F로 변환해서 나타냈다.

 

따라서 마지막 if문을 보면 300-84=216 b의 값이 216이나오면된다.

 

0x30 -> 0x2F  는 1을 뺀 값이다.

216 -> 자릿수에 1씩 빼면 105가나온다.

105 -> 0x31 0x30 0x35 

따라서 argument 값에 105를 입력하면 정답이다.

 

 

 

 

'악성코드 분석' 카테고리의 다른 글

AntiReversing  (0) 2019.06.05
패스워드 알아내기  (0) 2019.06.04
어셈블리어 로 test.cpp 해석  (0) 2019.05.21
Debugger사용법, 간단한test.exe파일을 통해 분석  (0) 2019.05.17
기초지식(스택)  (0) 2019.05.16

+ Recent posts