WEBVTT

00:00.520 --> 00:01.870
안녕하세요, 환영합니다.

00:01.870 --> 00:09.910
이 동영상에서는 네이티브 EXE 파일의 멀웨어 분석을 위한 어셈블리 언어의 기본 사항에 대해 설명합니다.

00:11.200 --> 00:12.520
스택이란 무엇인가요?

00:13.230 --> 00:18.060
스택은 LIFO, 라스트 인, 퍼스트 아웃 데이터 구조의 약자입니다.

00:18.510 --> 00:23.100
로컬 변수와 함수의 반환 주소를 저장합니다.

00:23.860 --> 00:26.310
푸시, 팝, 콜, 레트 명령어를

00:26.730 --> 00:33.390
통해 액세스하며 스택의 RAM 메모리 레이아웃은 다음과 같습니다.

00:33.720 --> 00:40.230
여기 다이어그램과 같이 높은 주소에서 시작하여 더 많은 값을 푸시할수록 점점

00:40.230 --> 00:45.940
더 작은 주소가 사용되며, 낮은 주소가 스택의 맨 위에 있습니다.

00:45.960 --> 00:47.520
그래서 이 모든 것이 스택입니다.

00:47.520 --> 00:56.670
여기는 RAM 메모리의 일부이며, -는 베이스 포인터로 스택 하단의 주소를 저장하는

00:56.670 --> 00:58.740
레지스터입니다.

00:59.130 --> 01:05.590
는 스택 상단의 주소를 저장하는 또 다른 포인터입니다.

01:05.610 --> 01:11.130
따라서 이들은 모두 스택을 만드는 데 유용한 레지스터입니다.

01:11.940 --> 01:12.970
힙이란 무엇인가요?

01:13.330 --> 01:16.870
힙은 메모리를 전역적으로 저장하는 데 사용됩니다.

01:17.110 --> 01:20.740
전역에 저장되므로 모든 함수가 액세스할 수 있습니다.

01:21.130 --> 01:24.310
일반적으로 프로그램의 데이터 섹션에 저장됩니다.

01:25.240 --> 01:26.490
이 API에서는 RTL

01:26.530 --> 01:30.190
할당 힙을 사용하여 힙을 생성할 수 있습니다.

01:31.060 --> 01:31.690
멀웨어는

01:31.720 --> 01:39.280
힙을 사용할 모든 것을 저장하는 영역으로 사용하며, 이 API 기능에 대한 Google 설명에서

01:39.280 --> 01:43.120
MSDN 도움말을 찾아볼 수 있습니다.

01:43.570 --> 01:45.640
다음으로 CPU 레지스터를 살펴봅니다.

01:46.180 --> 01:49.960
CPU 레지스터는 다음과 같은

01:51.400 --> 01:59.680
레지스터로 구성됩니다. - 는 일반적으로 산술 연산을 위한 누산기로 알려져 있습니다.

02:00.100 --> 02:02.710
- 는 데이터를 가리키는 기본 포인터입니다.

02:03.700 --> 02:08.800
- 는 일반적으로 명령어 이동, 회전 및 반복을 위한 카운터입니다.

02:09.700 --> 02:14.320
- 는 데이터 연산 및 입출력용입니다. - 는 소스 인덱스이며,

02:14.320 --> 02:16.510
문자열 연산에서 소스에

02:16.630 --> 02:23.500
대한 포인터입니다. - 는 문자열 연산에서 대상에 대한 대상 인덱스 포인터입니다.

02:24.100 --> 02:28.430
- 는 앞서 살펴본 스택의 바닥을 가리키는 베이스 포인터입니다.

02:28.820 --> 02:35.960
- 는 스택의 맨 위를 가리키는 스택 포인터이고, -는 실행할 다음 명령어의 주소를

02:35.960 --> 02:39.710
저장하는 명령어 포인터입니다.

02:40.280 --> 02:42.140
세그먼트 레지스터도 있습니다.

02:42.150 --> 02:44.690
- 는 스택 포인터입니다.

02:44.810 --> 02:46.940
- 는 코드 포인터입니다.

02:46.980 --> 02:49.490
- 데이터 포인터 등을 사용할 수 있습니다.

02:49.520 --> 02:55.220
중요한 것은 -, -, -이며, 이를 세그먼트 레지스터라고 합니다.

02:55.310 --> 02:59.060
예를 들어 금전 등록기와 같은 등록기의 일부에 액세스할

02:59.150 --> 03:00.140
수 있습니다.

03:00.440 --> 03:07.640
이 예는 32비트 레지스터로, 4바이트로 구성되며 DWORD라고도 하는 4바이트, 32비트라고

03:07.640 --> 03:08.930
합니다.

03:08.960 --> 03:14.720
실제로 단어의 절반인 아래쪽 2바이트(16비트)에만 액세스하려는

03:14.720 --> 03:19.520
경우 이 기호를 대신 사용할 수 있습니다.

03:19.910 --> 03:28.250
가장 아래쪽 바이트, 즉 8비트에 액세스하려면 -를 사용하면 됩니다.

03:29.200 --> 03:32.050
따라서 하위 바이트에 액세스합니다.

03:32.440 --> 03:33.970
- 는 더 높은 바이트에 액세스합니다.

03:35.050 --> 03:36.430
예를 들면 다음과 같습니다.

03:36.430 --> 03:41.650
가 1, 2, 3, 4, 5, 6, 7, 8의 16진수 값을 가지고 있다고 가정합니다.

03:41.680 --> 03:45.730
에 액세스하려는 경우 DWORD입니다.

03:45.760 --> 03:49.300
단어에 액세스하려면 -를 사용합니다.

03:49.570 --> 03:54.670
상위 바이트에 액세스하려면 -를 사용하고 하위 바이트에 액세스하려면 -를 사용합니다.

03:54.700 --> 03:56.020
이것이 바로 여러분이 얻게 될 것입니다.

03:56.230 --> 03:58.270
- 를 누르면 5, 6, 7, 8이 나옵니다.

03:58.660 --> 04:02.350
- 를 누르면 5, 6, -를 누르면 7, 8이 나옵니다.

04:02.920 --> 04:05.740
다른 모든 레지스터에도 동일하게 적용됩니다.

04:05.770 --> 04:13.990
예를 들어 -에 액세스하는 경우 단어에 -을 사용하고, 낮은 바이트는 -, 높은 바이트는

04:13.990 --> 04:17.080
-을 사용하는 식입니다.

04:17.680 --> 04:19.630
깃발 등록부도 있습니다.

04:19.720 --> 04:24.100
각 비트가 1 또는 0을 포함하는 플래그 역할을 하는 레지스터입니다.

04:24.130 --> 04:26.050
중요한 것은 다음과 같습니다.

04:26.290 --> 04:28.510
CF는 캐리 플래그입니다.

04:28.540 --> 04:33.260
연산 결과가 대상 피연산자에 비해 너무 클 때 설정됩니다.

04:33.620 --> 04:34.850
0 플래그는 연산

04:35.030 --> 04:38.600
결과가 0과 같을 때 설정됩니다.

04:38.870 --> 04:42.530
연산 결과가 음수인 경우 부호 플래그가 설정됩니다.

04:42.680 --> 04:46.820
또한 단계별 디버깅을 수행하는 경우 트랩 플래그라고도

04:46.850 --> 04:54.770
하는 DF 플래그가 설정되며, 멀웨어에 안티 디버깅 기능이 있는 경우 가끔 이를 감지할 수 있습니다.

04:55.280 --> 04:57.050
어셈블리 언어 지침, 세 가지

04:57.200 --> 04:58.550
주요 카테고리.

04:58.580 --> 04:59.740
데이터 흐름(예:

04:59.750 --> 05:01.740
이동 명령어).

05:01.760 --> 05:02.720
제어 흐름(예: 푸시,

05:02.720 --> 05:03.320
호출, 점프)을

05:03.320 --> 05:03.650
제어할 수

05:03.650 --> 05:04.610
있습니다.

05:04.940 --> 05:06.050
산술 및 논리(예:

05:06.050 --> 05:06.890
XOR, OR,

05:06.890 --> 05:09.320
MUL, ADD).

05:10.490 --> 05:14.180
데이터 전송 명령의 예는 이동입니다.

05:14.480 --> 05:15.720
예를 들어 소스를

05:15.740 --> 05:18.830
목적지로 이동하는 것이 목적입니다.

05:18.830 --> 05:25.760
예를 들어 주소에 저장된 값을 - 레지스터로 이동합니다.

05:26.150 --> 05:32.600
예를 들어 이동 제로 확장, 즉 소스에서 대상으로 이동을 의미하는 MOVZX입니다.

05:32.600 --> 05:39.950
따라서 16진수 123을 -로 이동하고 상위 비트는 0으로 채웁니다.

05:40.850 --> 05:44.870
LEA, 유효 주소(예: 소스에서 목적지까지)를 로드합니다.

05:45.110 --> 05:51.800
에서 40인치 16진수를 뺀 뒤의 주소를 로드하고 결과

05:51.800 --> 05:58.940
주소를 -에 저장합니다. XCHG는 두 레지스터 간의 값을 교환하는 것입니다.

05:58.940 --> 06:05.030
예를 들어, 소스 및 대상 교환은 소스에 있는 모든 것을 대상으로, 대상에 있는 모든 것을

06:05.030 --> 06:06.680
소스로 바꿉니다.

06:07.100 --> 06:10.190
제어 흐름 명령의 예: 점프.

06:10.760 --> 06:17.960
따라서 이것은 무조건 점프이며, 그 이전의 조건이 무엇이든 상관없이 점프합니다.

06:18.200 --> 06:23.210
예: 이 주소에 저장된 값으로 이동합니다.

06:23.660 --> 06:25.400
JZ는 조건부 점프입니다.

06:25.790 --> 06:28.250
0 플래그가 1인 경우에만 점프합니다.

06:28.250 --> 06:36.970
예: JZ 주소. 0이 아닌 점프, 0이 아닌 점프는 0 플래그가 0이면 점프합니다.

06:37.150 --> 06:41.020
점프 앞에 테스트 또는 비교 명령어가 오는 경우.

06:41.230 --> 06:47.260
그러나 점프는 무조건적인 점프이며 테스트나 비교를 전제로 하지 않습니다.

06:48.730 --> 06:50.620
다음은 점프의 예입니다.

06:51.280 --> 06:58.180
따라서 이 점프는 여기서 비교가 0과 같을 때만 발생합니다.

06:58.180 --> 07:02.560
예를 들어 - 마이너스 -가 0이면 점프합니다.

07:03.220 --> 07:05.020
이 JB는 아래 점프입니다.

07:05.020 --> 07:15.340
따라서 아래의 점프는 -에서 저장된 값을 뺀 값과 C를 더한 값이 0보다 작을 경우에만 발생합니다.

07:15.370 --> 07:16.330
그러면 점프합니다.

07:18.100 --> 07:19.570
그리고 여기에서는 점프가 동일하지

07:19.570 --> 07:20.260
않습니다.

07:20.290 --> 07:21.310
점프가 같지

07:21.310 --> 07:27.540
않음은 - 마이너스가 0이 아닌 경우에만 발생합니다.

07:27.550 --> 07:28.690
그러면 해당 항목만 점프합니다.

07:30.030 --> 07:35.010
산술 명령의 예: ADD, SUB, IMUL 및 INC.

07:35.010 --> 07:37.110
예를 들어 소스에 대상을

07:37.880 --> 07:43.310
추가하면 소스에 있는 내용을 대상에 추가하고 그 결과를 대상에

07:43.310 --> 07:45.230
저장하는 것입니다.

07:45.720 --> 07:48.410
SUB와 동일하지만 마이너스만 빼면 됩니다.

07:48.790 --> 07:55.340
IMUL은 소스에 값을 곱한 다음 그 결과를 대상에 저장하는 곳입니다.

07:55.370 --> 07:59.840
증분, INC는 레지스터에 있는 모든 항목을 1씩 증가시키는 것을 의미합니다.

07:59.840 --> 08:01.550
다음은 그 예입니다.

08:02.120 --> 08:04.070
로직 명령의 예

08:04.100 --> 08:07.060
XOR은 소스, 소스, 대상과 같이 비트 단위의

08:07.080 --> 08:08.930
XOR을 수행합니다.

08:09.790 --> 08:11.530
그리고 여기서 왼쪽으로 이동합니다.

08:11.560 --> 08:18.010
즉, 소스에 표시된 비트 수만큼 모든 비트를 왼쪽으로 이동합니다.

08:18.040 --> 08:25.630
예를 들어 -가 1이면 여기서 모든 비트를 왼쪽으로 1씩 이동하고 비트 단위로 AND를 수행합니다.

08:25.660 --> 08:29.950
따라서 여기서는 소스 및 대상을 사용하여 AND 연산을 수행합니다.

08:31.600 --> 08:33.400
지침을 테스트하고 비교합니다.

08:33.820 --> 08:37.910
여기서 두 피연산자에 대해 비트 단위 AND를 수행합니다.

08:37.930 --> 08:40.930
결과가 0이면 0 플래그가 설정됩니다.

08:41.110 --> 08:43.030
조건부 점프와 함께 자주 사용됩니다.

08:43.660 --> 08:48.680
CMP는 첫 번째 연산과 두 번째 연산을 뺄셈으로 비교하는 것입니다.

08:48.700 --> 08:56.380
여기서는 인자 1에서 인자 2를 뺀 예제입니다. 앞서 설명한 것처럼 점프 지침은 항상 테스트

08:56.380 --> 09:02.320
또는 비교 직후에 나타납니다. 반환값: - 레지스터는 함수 호출의

09:02.620 --> 09:06.250
반환값을 저장하는 데 사용됩니다.

09:06.520 --> 09:14.140
반환 값은 정수이거나 0 또는 음수일 수 있으며, 모든 F는 16진수로 표시됩니다.

09:14.170 --> 09:18.160
예를 들어 이 16진수 주소와 같은 주소일 수도 있습니다.

09:19.120 --> 09:25.360
예를 들어 x64dbg의 이 출력을 살펴보겠습니다.

09:25.900 --> 09:28.810
여기 푸시 7이 표시됩니다.

09:28.810 --> 09:35.090
따라서 7을 누르면 7을 여기 스택으로 밀어넣은 다음 호출합니다. 이 함수를 호출하면 호출 결과를

09:35.120 --> 09:38.030
-로 반환합니다.

09:39.680 --> 09:43.770
여기까지 어셈블리 언어에 대한 입문서입니다.

09:43.790 --> 09:45.020
시청해 주셔서 감사합니다.
