📌 근거리 네트워트 (LAN, Local Area Network)

  • 범위가 건물 안이나 특정지역인 네트워크이다.
  • 유선 케이블, 적외선 링크, 무선 송수신기 등을 이용하여 통신한다.
  • 한 건물 또는 인접한 건물군 내에 있는 네트워크는 하나의 LAN으로 간주되며 집이나 빌딩 안에 있는 사무실 등 지리적으로 제한된 곳에서 컴퓨터와 프린터, 스캐너 등을 연결할 수 있는 네트워크이다.
  • 서로 다른 LAN을 연결하여 사용할 수 있다.

 

 📌 도시 지역 네트워크 (MAN, Metropolitan Area Network)

  • LAN보다 넓은 영역이고 WAN보다 작은 영역을 커버한다.
  • 떨어져 있지만 동일하거나 다른 도시에 상주하는 두 대 이상의 컴퓨터를 연결한다.
  • 예시
    고객에게 고속 DSL 회선을 제공할 수 있는 회사의 일부 네트워크나 케이블 TV 네트워크가 있다.
    지역 또는 도시 내에 위치한 다양한 경찰서를 서로 연결하는 데 사용할 수 있다. 경찰관은 인터넷 연결 없이 쉽게 통신할 수 있고 중요한 데이터와 긴급 메시지를 네트워크를 통해 신속하게 전달할 수 있다.

 

 📌 광역 네트워크 (WAN, Wide Area Network)

  • 두 개 이상의 근거리 네트워크를 넓은 지역에 걸쳐 연결하는 것이다.
  • 근거리 네트워크에 포함되지 않은 멀리 떨어진 컴퓨터 사이에서도 광역 네트워크를 이용하여 서로 통신할 수 있다.
  • LAN보다 오류 발생 확률이 크고, 속도는 느리며, 비용은 많이 든다.
  • 예시
    어떤 기업의 본사는 서울에 있고 생산 공장은 지방에 있을 수 있다. 이 둘 간에 데이터와 프로그램 등을 공유하려고 기존 전화선에 라우터를 연결하여 광역 네트워크를 구성하기도 한다.

 

 📌 인트라넷 (Intranet)

  • 인터넷에서 사용하는 회선과 여러 기반 기술을 이용하여 구축하는 사설 네트워크이다.
  • 기업에서 내부망, 외부망을 따로 관리하는 경우가 있는데 이러한 경우 내부망이 바로 인트라넷이다.
  • 예시
    각 지방에 분산된 대학 캠퍼스들을 전용회선을 이용하여 네트워크로 연결한다면 지불 비용이 많이 들 것이다. 하지만 인터넷을 이용하면 쉽게 해결할 수 있다.
  • 아무리 멀리 떨어져 있어도 각 지방의 캠퍼스들을 ISP까지만 연결하면 인터넷을 이용하여 저렴한 비용으로 사설 네트워크를 구축할 수 있다.

 

 


이미지 출처

2020 데이터통신 및 네트워크 수업 자료

 📌 어셈블리어 실습 방법 - 코드 패치

1부터 100까지의 합 코드를 작성하기 전에 Immunity Debugger에서 코드 패치를 이용하여 새로운 코드를 작성하는 방법을 다루려고 한다.

 

디버거에서 아무 실행 파일(*.exe)을 열고, 코드 부분을 더블 클릭해서 수정하면 된다.

코드를 더블 클릭하면 

왼쪽 처럼 뜰 텐데, 여기서 코드를 수정하고 Assemble을 누르면 해당 줄의 코드가 변경되고 밑에는 NOP으로 모두 변경된다.

아래로 순서대로 코드 패치를 진행하면 된다.

 

 

 📌 1부터 100까지의 합 ver.1 (레지스터 3개 사용)

  1. EAX, EBX값을 1로 초기화 시키고 EBX를 1씩 증가시키면서 EAX에 EBX를 더해준다.
  2. LOOP는 EBX가 100이 될 때까지 돈다. (ECX가 0일 때까지 돈다. 여기서 LOOP 명령어는 ECX를 먼저 1감소하고 0인지 아닌지 비교함에 주의)

💻 코드

  1. EAX를 1로 초기화 시킨다.
  2. EBX를 1로 초기화 시킨다.
  3. LOOP는 EBX가 100일 때까지 더하려면 2~100까지 즉 99번 돌아야 하므로 ECX값을 99로 정해 줘야함. 99를 16진수로 하면 63이기 때문에 63으로 초기화 시킨다.
  4. 보기 편하게 한 줄 띄우기 위해 NOP 사용. (해당 줄은 없어도 된다.)
  5. EBX를 1씩 증가시킨다.
    (1~100을 더하는데 EAX가 1이고 EBX도 1이기 때문에 EBX를 먼저 1증가시키고 EAX에 더하는 것을 반복한다.)
  6. EAX에 EBX를 더해서 EAX에 저장한다.
  7. 5번 줄과 6번줄을 EBX가 100이 될 때까지 (CX가 0이 될 때까지)반복한다.

 

💡 레지스터 변화 확인

1.  EAX, EBX, ECX 초기화

2.  더하는 과정

EBX값을 1 증가시킨 후 EAX에 EBX를 더한다.

 

3. 결과

ECX가 0이 되면 LOOP를 멈춘다. 99번 돌았기 때문에 이 시점에서 EBX값을 보면 1에서 99를 더한 64(10진수로 100)이다.

또한 EAX 값은 1에서 100까지를 더한 13BA(10진수로 5050)가 되어있는 것을 확인할 수 있다.

 

 

📌 1부터 100까지의 합 ver.2 (레지스터 2개 사용)

  1. EAX값을 0으로 초기화 시키고 ECX가 100부터 0까지 -1씩 하면서 ECX를 EAX를 더한다.
  2. LOOP는 ECX가 0일 때까지 돈다. (여기서 LOOP 명령어는 ECX를 먼저 1감소하고 0인지 아닌지 비교함에 주의)

💻 코드

  1. EAX를 0으로 초기화 시킨다.
  2. LOOP는 1~100을 더해야 하므로 ECX값을 100으로 정해 줘야함.
    100를 16진수로 하면 64이기 때문에 64으로 초기화 시킨다.
  3. EAX에 ECX를 더한다. (처음엔 100, LOOP 한 번 돌 때 ECX가 -1되므로 다음엔 99를 더하는 식)
  4. ADD EAX, ECX를 100번 돈다.

 

💡 레지스터 변화 확인

1.  EAX, ECX 초기화

2.  더하는 과정

ECX 값을 EAX에 더해주고 ECX값은 루프를 돌면서 1씩 감소한다.

3.  결과

ECX가 0이 되면 LOOP를 멈춘다.

EAX 값은 100에서 1까지를 더한 13BA(10진수로 5050)가 되어있는 것을 확인할 수 있다.

 

 

 📌 느낀점

레지스터 3개를 사용할 땐 2 ~ 100까지 99번 돌아야 해서 ECX 레지스터에 99를 16진수로 바꾼 63을 넣어줬는데,레지스터 2개를 사용할 땐 ECX가 직접 합에 관여하는 변수였기 때문에 1 ~ 100을 더해야해서 100을 16진수로 바꾼 64를 넣어주는 과정이 헷갈렸었다.

지금 생각해보면 레지스터 3개 사용할 때 EAX, EBX 초기값을 0으로 넣고 총 100번(1부터 100까지) 도는 걸로 생각해서 ECX에 64를 넣는 것이 좀 더 수월했을 수도 있을 것 같다.

 

'Security > Windows' 카테고리의 다른 글

[Immunity Debugger] sum.exe 파일 분석  (0) 2022.03.06

 📌 분석 실습 보고서 작성

  1. 메인함수 찾기
  2. 서브함수 찾기
  3. 레지스터(EAX, EIP) 변경 확인
  4. 스택(RETURN주소 등) 변경 확인

 

 📌 소스 코드 및 분석 방법 설명

소스 코드: sum.c

#include <stdio.h>

int sum(int a, int b) {
	return a + b;
}

int minus(int a, int b) {
	return a - b;
}

int main() {
	int x = 9;
    int y = 7;
    printf("sum: %d \n", sum(x, y));
    printf("minus: %d \n", minus(x, y));
}

sum.c를 컴파일하여 실행 파일로 만듭니다.

그 이후 sum.exe를 Immunity Debugger에서 실행 시킵니다.

 

 

 1️⃣ 메인함수 찾기

처음 sum.exe 파일을 실행시키면 이런 화면이 뜬다.

step over(F8)로 넘어가다 보면 4번째 줄의 CALL sum.00401000을 만난 후

터미널에 결과가 나오고 함수가 종료된다.

그럼 CALL sum.00401000에 break point를 걸고 재시작(ctrl+F2) 후

해당 명령어에서 step into(F7)을 해서 해당 함수 안으로 들어간다.

그러면 해당 화면이 나온다. 여기서 main 함수로 추정되는 명령에서 step over를 하면서 터미널에 값이 나오는지 확인한다.

이 두 함수를 실행해도 터미널에 결과값이 나오지 않으니 main 함수가 아닌 걸 알 수 있다.

Step over로 넘어가다가 CALL sum.00401368을 만나 실행하면

터미널에 결과값이 출력된다. 그러므로 sum.00401368이 main 함수이다.
해당 명령어에 break point를 걸고 재시작 후 step into(F7)을 해서 main 함수로 들어간다.

 

 

 2️⃣ 메인 함수 실행 후 스택, 레지스터 값 확인

Main 함수로 들어가면 먼저 return해야하는 주소를 스택에 쌓고 처음에 원래의 EBP값을 스택에 push해준다.

그리고 원래의 ESP값을 새롭게 EBP값으로 지정해준다.

이 EBP값은 해당 함수만의 EBP값이다. 이후 EBP값을 16진수 20만큼 늘려 놓는다.

이는 변수를 저장해 놓는 곳을 확보하는 것이다.
실제로 immunity debugger에서 보자면

아까 main함수 다음 명령어 주소인 004010FD가 main 함수가 실행되자 마자 스택에 쌓이는 것을 볼 수 있다.

또한 6, 7번째 줄을 실행시키면 int x = 9, int y = 7인 코드가 실행되며 스택에 쌓이게 된다.

레지스터 값은 명령어에 따라 바뀌게 된다.

여기서 중요한 점은 스택에 9, 7 순으로 쌓였는데 스택은 LIFO 구조이므로 7이 먼저 EAX에 들어간다는 것이다.

EIP값은 늘 바로 이후에 실행할 명령어 주소를 담고 있다.

 

 

 3️⃣ 서브  함수 찾기 (sum, minus)

서브 함수도 메인 함수 찾는 것과 같이 터미널을 확인하며 진행한다.

서브 함수(sum, minus) 찾는 것은 비교적 쉬웠는데, 오른쪽에 보면 프린트문이 나와있는 것을 볼 수 있다.

역시나 해당 코드까지 실행해보니 터미널에 sum()과 minus() 결과값이 나왔다.

서브 함수인 sum(), minus()에도 breakpoint를 걸고 step into(F7)로 레지스터와 스택의 변경을 확인해보도록 한다.

 

 

4️⃣ 서브 함수의 레지스터 스택 값 확인

먼저 sum() 함수에서 step into(F7)로 들어간다. 일단 돌아 가야 할 리턴 주소 값을 스택에 넣는다.

이후 main함수 실행했던 것과 같이 원래의 EBP값은 스택으로, 원래의 ESP값을 새로운 EBP값으로 넣어주는 것을 볼 수 있다.

sum함수를 실제로 계산하는 부분은 5번째 줄이다. 그 전에 EDX에 9를, EAX에 7을 넣는 작업을 한다.

이것은 4번째 줄까지 실행시킨 후의 레지스터 값이다.

5번째 줄을 실행하면 EAX, EDX를 더해 다시 EAX에 저장한다.

EIP값은 여전히 늘 다음 명령어를 가리킨다.

헷갈리지 말아야할 점은 현재 실행되고 있는 명령어가 아니라 다음에 실행할 명령어라는 것이다.

예를 들어,

이렇게 0030125B POP EBP를 수행하면 밑에 줄에 파란 줄이 생기고

레지스터에는 이렇게 나온다.

EIP값이 파란 줄 주소와 같으므로 혼란이 올 수 있는 점을 유의한다.

sum()에서 RETN을 만나서 나온 후 print문을 만나면 터미널에 출력된다.

 

minus함수도 sum함수와 비슷하게 작용한다.

여기서 minus()함수인 CALL sum.0040135D에서 step into(F7)을 한다.

sum()과의 차이점은 EDX를 사용하지 않는다는 것이다. 순서대로 레지스터 값을 보면

이런 식으로 해당 명령어에 따라 ESP, EBP, EAX가 변화하고 EIP는 다음 실행할 명령어로 계속 바뀐다.

스택 값은 sum과 똑같이 작용한다. 하나만 보자면

처음 minus 실행하면 리턴 값이 스택에 쌓이게 된다.

리턴 후 print문을 만나면 터미널에 출력된다.

이후 step over(F8)로 실행하다가 ExitProcess를 만나면 종료된다.

 

 📌 느낀 점

 자료구조 때 배웠던 스택의 특징을 어셈블리어를 통해 실습할 수 있었다.

실행 파일이다 보니 이미 실행한 코드 한 줄을 다시 되돌릴 수가 없어서 다시 재시작 후 처음부터 봐야해서 귀찮았다 ,,

Immunity Debugger도 처음 사용해봤는데, 파란 줄로 뜨는 것이 현재 실행한 코드가 아닌 다음 실행할 코드인 게 상당히 헷갈렸다. 이럴 땐 EIP를 꼭 참고하는 걸로 !

+ Recent posts