Jiyong's STUDY
calc.exe 핸드레이 본문
순서대로 더하는 함수, 빼는 함수, 곱하는 함수, 나누는 함수(리턴은 나머지)다.
int oper(int a, int b){
return a (op) b;
}
로 보인다.
함수 기본구조
push ebp
mov ebp, esp
...
pop ebp
retn (default = eax 리턴)
add a, b eax에 a+b 16진수
sub a, b eax에 a-b 16진수
imul a, b eax에 a*b 16진수
idiv [a] eax에 eax에 저장된 값 / a에 저장된 값 연산 이후 16진수 몫, edx에 16진수 나머지
cdq는 idiv로 나눗셈 계산을 할 때, 피제수의 크기를 늘려주는 역할을 한다.
예를 들어 제수가 32bit이고 피제수가 32bit일 때, 계산이 정상적으로 되지 않는다.
그 때 피제수를 64bit로 바꾸면 제대로 연산이 된다.
00401030 함수에서 idiv 연산 이후
mov eax, edx 연산을 했으므로 리턴을 할 값은 몫이 아니라 나머지가 된다
sub esp, 18. 이 안에서 사용할 변수의 총 크기가 18byte인걸 유추할 수 있음.
(int형 2개, char형 1개, double 1개 합 18)
추가로 변수의 초기화 선언은 없는 것으로 보임.
scanf, printf가 출력하거나 입력받을 자료는 push calc.xxxxxxx로 메모리 공간이 할당되어 있거나
내용이 들어있음
lea eax, dword...
push eax 등으로 scanf 함수에 &연산으로 인자를 전달해줌
fild = 정수 로드 (스택으로 꺼내 옴)
fidiv = 스택에 있는 값 / fidiv의 인자. 계산 결과는 스택으로
fstp dest = 스택에 있는 값을 dest로 pop시키고 st0에 있는 값을 st7로 옮김
위 3줄에서 입력받은 정수 두개 나머지 연산
아래 jmp 연산 전까지 %c로 받은 연산자 (operator)를 분류하는 과정
ja(jump if above) cmp로 비교 후에 앞에 있는게 크면 jmp
함수가 끝날 때 마다 add esp로 공간을 확보하는 것을 보면 __cdecl으로 함수를 호출함. (c 표준)
위의 연산 함수 진입 전에 mov로 edx, ecx에 인자를 넣어 준 뒤에 push edx, push ecx로
두 레지스터에 있는 값(인자)을 함수로 전달함.
함수에서 연산 후 리턴받은 값은 eax에 있음.
연산한 값을 push로 인자 전달을 하고, 인자 전달을 하나하나 함. (맨 뒤부터 인자 전달을 함)
이후 사용한 공간 정리를 caller인 main이 add esp로 함.
fld = dword를 floating point로 확장시킴 // 정수->실수 형변환 과정으로 보임
%.2lf로 받아왔으니 float형이 아니라 double형으로 형변환함
나머지 계산 부분 "[>] %d % %d = %d"부분을 패치하여
"[>] %d %% %d = %d"로 바꿔야 제대로 된 결과를 볼 수 있다.
(이전엔 인자1 %d= 인자2로 출력되고, 나머지값인 인자3은 출력되지 않음.
패치 이후엔 인자1 % 인자2 = 인자3으로 정상 출력)
같은 위치(main 함수 리턴 직전)로 jmp가 반복되는 것 보면 if or switch case문을 사용한 것으로 보임.
switch table을 확인했으니 switch~case문을 사용함을 알 수 있음.
'보안 > 리버싱, 어셈블리' 카테고리의 다른 글
[PE구조] IMAGE_DOS_HEADER (0) | 2020.08.03 |
---|---|
함수 스택 규약 (0) | 2020.07.20 |
[기초] 스택프레임 구조 (0) | 2020.07.17 |
[기초] 리틀 엔디언 (0) | 2020.07.17 |
[기초] Hello World 리버싱 문자열 패치 (0) | 2020.07.16 |