※ OS : Windows환경의 악성코드
1. 위장 악성코드
▶ 악성코드 제작자는 악성코드를 은닉하기 위해 여러가지 방법을 개발한다.
▶ 즉, 탐지를 우회하기 위해 위장 실행 기법을 개발한다.
2. Launchers(실행기)
(1) Launcher란?
[1] Loader라고도 부르며 현재 실행하고 있거나 추후에 (은밀하게) 실행하기 위해 자기자신이나 다른 악성코드를 설정하는 악성코드이다.
[2] 편의상 exploit이라고 생각하려고 한다.
(2) Launcher가 필요한 이유?
[1] 나쁜 짓 할 때 사용자에게 걸리지 않으려고? 설정하기 위해서..ㅎ
(3) Launcher가 로딩할 악성코드를 포함한 경우
[1] .exe파일이나 .dll을 자신의 resource section에 가지고 있다.
[2] PE파일은 resource section은 .exe에서 사용하기는 하지만, 실행이 가능한 영역은 아니다.
[3] resource section은 보통 아이콘, 이미지, 메뉴, 문자열 등을 가지고 있다.
[4] Launcher가 실행될 때 resource section에서 내장된 .exe나 .dll을 추출해서 실행한다.
(4) 만약 resource section이 압축이나 암호화 됐다면?
[1] 악성코드를 로딩하기 위해 resource section에서 추출해야 한다.
[2] 추출 시에는 FindResource, LoadResource, SizeofResource와 같은 resource 처리 API를 사용해야 한다.
[3] 필요하다면 관리자권한을 얻기 위해 권한상승도 해야한다.
▶ Launcher를 탐지하는데 좋은 방법 중 하나는 권한 상승과 관련된 코드가 있는지 찾는 것이다.
3. Process Injection
(1) 프로세스 인젝션이란?
[1] 코드를 실행 중인 프로세스에 인젝션 한다.
[2] 가장 보편화되어 있으며 악성행위(나쁜짓)를 숨기기 위해 사용한다.
[3] 호스트기반 방화벽과 프로세스에 특화된 보안 매커니즘을 우회할 때 사용한다.
[4] 프로세스 인젝션에 사용되는 API는?
▶ VirtualAllocEx : 원격 프로세스의 메모리에 공간을 할당한다.
▶ WriteProcessMemory : 할당된 공간에 데이터를 쓸 때 사용된다.
(2) DLL Injection
[1] 원격의 프로세스가 악의적인 DLL을 로딩하게 하는 프로세스 인젝션 중 하나이다.
[2] 가장 흔히 사용되는 위장 로딩 기법으로 LoadLibrary를 호출하는 원격프로세스에 코드를 삽입해 해당 프로세스가 DLL을 강제로 로드하게 된다.
[3] 감염된 프로세스가 악의적인 DLL을 로딩하면 OS는 DLL의 DllMain함수를 호출한다.
[4] DllMain에 악의적인 코드가 포함되어 있으며, 해당프로세스의 메모리에 대한 접근권한을 갖는다.
[5] 동작하는 모든 작업은 감염된 프로세스에 의존적이다.
[6] 악성코드 로더는 프로세스 기반 방화벽에 차단되서 인젝션 전까지는 다른 프로세스에 접근이 불가능하다.
정리는 여기까지 하고 피피티로 이미 정리한 내용을 올리려고 합니다~~
▶ 이 말은 Launcher를 탐지하는 좋은 방법 중 하나는 권한상승 관련된 코드를 찾는 것을 말합니다.
▶ DLL은 플러그인이나 기능추가 시 사용되고 다른 프로그램이 불러서 사용한다.
▶ 이 말은 DLL을 프로세스에 삽입하면 DllMain이 실행될 것이고,
▶ 그렇다면 DllMain에 악성코드를 넣어 실행하도록 한다.
▶ 원래 DllMain은 프로세스나 스레드별로 초기화를 수행하는 목적으로 호출된다.
▶ 인젝션할 프로세스에 대한 제어권을 얻으려면?? PID가 있어야 한다.
▶ GetWindowThreadProcessId()의 파라미터로 윈도우번호와 PID를 가져올 주소 를 넣는다.
▶ 프로세스의 핸들을 얻었다는 것은 프로세스가 사용하는 메모리 공간에 접근이 가능하다!!
▶ 프로세스가 사용하는 메모리공간에 호출할 DLL의 경로와 길이
▶ 인젝션할 DLL경로를 프로세스에 기록하기 위해서는 공간을 확보한다.
▶ 프로세스에서 DLL을 로드하려면 LoadLibrary() 함수를 사용해야 하는데
▶ LoadLibrary함수는 kernel32.dll에 들어있다.
▶ 이제 LoadLibrary()함수만 호출하면 내가 만든 dll이 프로세스 내부에 올라가게 된다.
▶ 그렇다면 LoadLibrary()를 어떻게 호출할까..?
▶ 원격에서 프로세스 내부에 스레드를 생성하고
▶ 스레드의 시작지점을 LoadLibrary()함수의 주소로 작성한다.
▶ 생성이 되었다면 DLL이 인젝션되고 악성스크립트가 있는 DllMain()함수가 동작한다.
▶ DLL이 로드되었을 때 운영체제는 DllMain()함수를 호출하고 운영체제가 호출하는 함수는 검사대상이 아니다.
▶ 키로거를 실행시키면 검사를 하지만..
▶ 메모장에 키로거 코드가 작성된 dllmain이 있는 dll을 추가한다면 입력한 내용이 외부로 전송되도록 할 수 있다.
▶ 걸리지 않는 이유는 메모장은 안전한 프로그램이기 때문이다.
▶ 대기상태의 프로세스를 생성 한다.
▶ Suspended State 프로세스는 메모리에 로드는 했지만 프로세스의 메인스레드가 대기 중인 상태 를 의미한다.
▶ 즉, 외부프로그램이 해당프로세스의 메인스레드를 부르기 전까지는 아무것도 하지 않는다.
▶ 메모리에 로드 후 ResumeThread() 함수가 호출될 때까지 대기 한다.
▶ 코드가 메모리에 올라가있지만 실행되지 않은 상태에서 정상코드를 메모리상에서 할당 해지한다.
▶ 이유는? 새로운 코드를 쓰기 위해서~
▶ 파라미터로는 후크프로시저의 유형을 지정하고, 후크프로시저의 포인터, 스레드식별자(TID)를 넣어줍니다.
▶ 아까와 동일하게 인젝션할 프로세스를 찾고 내부의 스레드 중 하나를 찾습니다.
▶ IAT는 어떤 라이브러리에서 어떤 함수를 사용하고 있는지를 기술한 테이블 을 말한다.
▶ 먼저 동기 함수 호출은 무엇일까? 일반적으로 우리가 함수를 호출하는 것을 말한다.
▶ 그렇다면 비동기 함수 호출은?? CALLBACK함수를 말한다.
▶ Callback함수란??
▶ 시스템에서 이벤트 발생시 자동으로 호출하는 형태
▶ 사용자가 호출하는 형태가 아니고...
▶ 회사에 가서 면접을 본 면접자들이 각자 회사로 전화하면 면접 결과도 나오지 않았는데 번거로운 상황이 발생한다.
▶ 그래서 회사가 결과가 나왔을 때 면접자들에게 통보해주는 방식과 비슷하게 생각하면 된다.
▶ Callback 함수의 형태
▶ 원형을 보면 파라미터가 포인터변수 하나를 받는데 잘 이용하면 개수 상관없이 어떤 데이터타입이라도 보낼 수 있다.
▶ 호출하는 방법은? CALLBACK함수이므로 사용자가 함수이름을 써서 직접 호출하지 않을 것으로 예상된다.
▶ Callback 함수를 호출하는 방법
▶ QueueUserAPC API를 이용해서 호출할 수 있다.
▶ APC Procedure의 function pointer를 넣어주고,
▶ APC Procedure를 호출할 thread를 넣어주고,
▶ APC Procedure의 parameter를 넣어준다.
▶ 검정색은 thread를 말하고 Waiting은 thread의 상태를 말한다.
▶ 아무 것도 하지 않는 대기 상태 이다.
▶ 생성되거나 Sleep()함수 사용했을 때 아무 것도 하지 않는 것과 동일 하다.
▶ Waiting 상태에서 특정 이벤트가 발생했을 때 OS가 Ready상태로 변경해준다.
▶ CPU에서 thread를 사용할 수 있다.
▶ 그러나 CPU에게서 단위시간을 할당받지 못했다.
▶ 현재 CPU가 thread를 수행하고 있다.
▶ 스케줄링에 따라 멈췄다가 동작하다가 반복 한다.
▶ Waiting상태에서 특정이벤트가 발생하면 OS가 thread를 Ready상태로 변경하고 CPU는 Ready상태인 Thread를 사용할 수 있다.
▶ Scheduling기법에 따라 Ready와 Running을 반복 한다.
▶ 앞에서 말한 것과 같이 Sleep()함수를 사용하면 Waiting상태에 도달하지만
▶ SleepEx()와 같이 Ex()가 붙은 API를 사용하면 alertable상태로 진입하도록 할지 선택할 수 있다.
▶ 2번째 파라미터에 true를 넣어준다면 thread는 alertable상태로 진입한다.
▶ Alertable상태로 진입한 thread는 APCQueue라고 부르는 Queue에서 Queueing된 정보가 있는지 확인한다.
▶ Queueing된 정보란? QueueUserAPC()함수에 의해 전달된 3가지 파라미터가 하나의 node가 된다.
▶ Thread는 Queue로부터 하나의 node를 빼와서 지정된 함수를 호출하게 된다.
▶ Alertable상태로 진입한 thread는 APCQueue라고 부르는 Queue에서 Queueing된 정보가 있는지 확인한다.
▶ Queueing된 정보란? QueueUserAPC()함수에 의해 전달된 3가지 파라미터가 하나의 node가 된다.
▶ Thread는 Queue로부터 하나의 node를 빼와서 지정된 함수를 호출하게 된다.
▶ 결국 APC Injection이란 정상적인 경로를 실행하기 전에 alertable상태인 thread를 선점해놓고
▶ APC_Queue에 QueueUserAPC() API를 넣고 alertable상태로 진입한 thread에게 Callback함수를 실행하도록 하는 것을 말한다.
▶ 내용이 복잡하지만 간단하게 설명하면
▶ 공격할 process를 찾기 위해 for문을 돌면서
▶ OpenProcess()로 Process의 핸들을 얻어온 후
▶ process 내에서 사용하는 thread 중 alertable상태에 진입할 가능성이 있는
▶ Thread는 OpenThread()로 thread의 핸들을 얻어온다.
▶ 즉, WaitFor..Ex 이런 함수를 찾는 방식을 말한다.
▶ QueueUserAPC()함수에 DLL을 로드하기 위해 kernel32.dll에 있는 LoadLibraryA()함수의 주소와 수행할 Thread의 핸들을 OpenThread()함수로 얻어서 넣고 DLL의 경로를 넣어준다.
▶ 해당 thread가 Alertable상태로 전환되었다면 APC_Queue에서 Queueing해서 node를 읽는다
▶ 이후 thread가 LoadLibraryA()함수를 수행한다.
댓글