본문으로 바로가기

어셈블리 프로그래밍 심화3

category Pwnable 2018. 7. 19. 11:50

1. 형변환


1) 큰 -> 작은 ( 딱히 명령어가 필요 없다. 상위 비트 값이 사라지기 때문이다.)


int a = 10;

short b = a;


2) 작은 -> 큰


short a = 10;

int b = a;


movzx (zero extend) 상위 비트가 0으로 확장되어 양수 부호를 유지한다.

movsx (sign extend) 상위 비트가 부호비트로 확장되어 부호를 유지한다.


1과 -1의 비트가 다르다는 것을 알아두자.


0000 0000 -> 1

1111 1111 -> -1




xor edx, edx를 통해 edx의 32bit 모두 0으로 채워진다.

mov dl, -2를 통해 dl의 8bit가 1111 1110으로 채워진다.

shl dl, 2를 통해 dl의 8bit가 1111 1000으로 채워진다.

shr dl, 2를 통해 dl의 8bit가 0011 1110으로 채워진다.


따라서 edx를 10진수로 출력하면 62가 출력된다.




xor edx, edx를 통해 edx의 32bit 모두 0으로 채워진다.

mov edx, -2를 통해 edx의 32bit가 11111111 11111111 11111111 11111110으로 채워진다.

shl edx, 2를 통해 edx의 32bit가 11111111 11111111 11111111 11111000 으로 채워진다.

shr edx, 2를 통해 edx의 32bit가 00111111 11111111 11111111 11111110 으로 채워진다. 


따라서 edx를 10진수로 출력하면 1073741822가 출력된다.



2. 관계 연산: >, <, =, <=, >=, !=


- cmp(compare)

- cmp vleft, vright -> eflag register가 설정된다.


첫 operand와 두번 째 operand의 값을 빼 두 값이 같은지 아닌지 비교한다.

sub 명령어와 행동 방식은 같다. sub는 뺀 결과는 첫 operand에 저장을 한다.

cmp는 oeprand에 저장하지 않는다. 단지 flag를 수정할 뿐이다.


1) vleft가 vright보다 큰 경우

-SF: 0, ZF: 0


2) vright가 vleft보다 큰 경우

-SF: 1, ZF: 0


3) vleft와 vright가 같은 경우

-SF: 0, ZF: 1




pushfd는 현재 flag register를 스택에 push하는 명령어이다.

출력이 647이라는 것은 현재 flag register 상태가 아래와 같다는 의미이다.


flag register : 00000000 00000000 00000010 10000111


하늘색으로 칠해진 0비트가 ZF를 나타낸다.

eax와 20은 다르기 때문에 ZF: 0으로 세팅된다.



3. 제어문: if, case - 기계어로는 차이가 거의 없다.


1) 무조건 분기: jmp


- jmp 주소

- jmp offset




main 함수로 들어가자마자 jmp second를 만나서

second로 이동한다. hello2를 출력하고 함수가 끝난다.


2) 조건 분기


- j조건



1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
main()
{
    int buffer;
    scanf("%s"&buffer);
 
    if(buffer < 10){
        printf("less than 10\n");
    }
 
}
cs




사용자로부터 scanf함수를 통해 buffer에 숫자를 입력받는다.

jl 명령을 통해 만일 buffer가 10보다 작으면 jmp if를 통해 "less than 10"을 출력한다.

buffer가 10보다 크면 jmp end를 통해 함수를 종료한다.


하지만 생각해보면 위 소스를 좀 더 이해하기 쉽게 재작성 할 수 있다.




우리가 원하는 조건을 반대로 생각하여 설정해주면 보다 분기를 줄여서 소스를 작성할 수 있다



예제) 아래 소스를 어셈블리어로 작성하시오


1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
main()
{
    int buffer;
    scanf("%s"&buffer);
 
    if(buffer < 10)
        printf("less than 10\n");
    else
        printf("bigger thean 10\n");
}
cs





3) 다중조건


아래의 소스와 같이 조건이 여러개일 수 있다.


and 조건일 경우


1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
main()
{
    int buffer;
    scanf("%s"&buffer);
 
    if( a < 10 && b > 1 && c == 5){
        printf("correct\n");
    }
}
cs




or 조건일 경우


1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
main()
{
    int buffer;
    scanf("%s"&buffer);
 
    if( a < 10 || b > 1 || c == 5){
        printf("correct\n");
    }
}
cs