마크다운 형식이랑 Html 정리

깃블로그에 좀 익숙해질 겸 마크다운과 html 치트시트 하나 만들려고 한다. 본문은 그냥 작성하면 된다.

Header one

제목 1은 # 제목

Header two

제목 2은 ## 제목

Header three

제목 3은 ### 제목

Header four

Header five
Header six

6까지 존재하지만, 그냥 3까지만 활용하는 게 좋을 거 같다.

Blockquotes

Single line blockquote:

한 줄 인용은 > 하나 치고 작성

Multi line blockquote with a cite reference:

여러 줄도 그냥 > 하나 치고 길게 길게 길게 적으면 된다

Steve Jobs — Apple Worldwide Developers’ Conference, 1997

마지막 누가 어디서 말했는지는 < cite> 사용해서 사람 감싸기

Tables

표는 내가 보기에 필요할 때 지피티 돌려서 만들어달라 하는 게 편하긴 하다.

Employee Salary  
John Doe $1 Because that’s all Steve Jobs needed for a salary.
Jane Doe $100K For all the blogging she does.
Fred Bloggs $100M Pictures are worth a thousand words, right? So Jane × 1,000.
Jane Bloggs $100B With hair like that?! Enough said.

위 표에 1행은 (#) 넣어서 링크를 만들었네. 대괄호로 문자열 감싸고 그 옆에 소괄호로 링크 넣으면 첨부된다. 아래는 행마다 정렬이 다르니까 참고 +) 표 위아래 모두 한 줄씩 띄워야 한다.

Header1 Header2 Header3
cell1 cell2 cell3
cell4 cell5 cell6
cell1 cell2 cell3
cell4 cell5 cell6
Foot1 Foot2 Foot3

Definition Lists

Definition List Title
Definition list division.

본문 아랫줄에 : 넣고 작성하면 들여쓰기가 된다.

Unordered Lists (Nested)

  • List item one
  • List item two
  • List item three
  • List item four 리스트는 그냥 참고하자.

Ordered List (Nested)

  1. List item one a. List item one 1. List item one 2. List item two 3. List item three 4. List item four b. List item two c. List item three d. List item four
  2. List item two
  3. List item three
  4. List item four

이것도 그냥 참고. a,b,c,d도 지원하나 해봤는데 안된다.

Address element

1 Infinite Loop
Cupertino, CA 95014
United States

< address> 넣고 주소 작성하면 기울기를 제공해주는데 특별한 건 모르겠다.

This is an example of a link.

오 소괄호 링크 옆에 큰따옴표로 문자열 작성하면 마우스 오버 텍스트 지원한다.

문자 스타일?

word-wrap: break-word; strikeout text italicize inserted keyboard text bold text H2O E = MC2

문자 스타일? 효과를 넣을 수 있다.

코드 작성

.post-title {
    margin: 0 0 5px;
    font-weight: bold;
    font-size: 38px;
    line-height: 1.2;
    and here's a line of some really, really, really, really long text, just to see how the PRE element handles it and to find out how it overflows;
}

< pre>로도 할 수 있는데 맠다 형식으로 작성하는 게 편한 거 같다. 아래 유튜브 추가하는 코드 첨부하면서 맠다 형식 넣었다.

Images

이미지 임베드 중요하지.. 근데 생각해보니까 이거 어느 폴더에 넣지? _screenshots에 넣어야 하나

placeholder placeholder placeholder

유튜브 첨부

<!-- responsive iframe. The framesize reduces proportionately when viewing in mobile -->
<div class="video-container">
  <iframe class="embed-responsive-item" src="..."></iframe>
</div>

이외에 Html로 임베드할 수 있는 요소

Howdy! This is an example blog post that shows several types of HTML content supported in this theme.

맠다 형식과 Html 스타일 비교

  • To bold text, use <strong>.
  • To italicize text, use <em>.
  • Abbreviations, like HTML should use <abbr>, with an optional title attribute for the full phrase.
  • Citations, like — Mark otto, should use <cite>.
  • Deleted text should use <del> and inserted text should use <ins>.
  • Superscript text uses <sup> and subscript text uses <sub>.

여러 코드 임베드 비교

// Example can be run directly in your JavaScript console

// Create a function that takes two arguments and returns the sum of those arguments
var adder = new Function("a", "b", "return a + b");

// Call the function
adder(2, 6);
// > 8
#container {
  float: left;
  margin: 0 -240px 0 0;
  width: 100%;
}
1
2
3
4
5
6
7
8
<nav class="pagination" role="navigation">
  {% if page.previous %}
    <a href="{{ site.url }}{{ page.previous.url }}" class="btn" title="{{ page.previous.title }}">Previous article</a>
  {% endif %}
  {% if page.next %}
    <a href="{{ site.url }}{{ page.next.url }}" class="btn" title="{{ page.next.title }}">Next article</a>
  {% endif %}
</nav><!-- /.pagination -->

여담인데 위 코드는 왜이렇게 어려워.

GitHub Gist embeds can also be used:

<script src="https://gist.github.com/mmistakes/77c68fbb07731a456805a7b473f47841.js"></script>

Which outputs as:

각주

Highlighting does not affect the meaning of the text itself; it is intended only for human readers.1


[DH] d

티스토리에서 백업한 글.

from Crypto.Util.number import *
from flag import flag

p = bytes_to_long(flag)
assert isPrime(p)
q = getPrime(256)
d = pow(65537, -1, (p - 1) * (q - 1))
print(d)
# 22800184635336356769510601710348610828272762269559262549105379768650621669527077640437441133467920490241918976205665073

p는 소수 

어떤 거 구해서 마지막에 long_to_bytes하면 그게 flag 

de=1(mod pq)

이걸 좀 풀어서 쓰면

de-1=n(q-1)(p-1)이다(n은 자연수) 

factorint로 소인수분해 하면 아래와 같다. 

일단 가장 큰 수는 256비트이기 때문에 조합할 경우의 수가 많지 않다. 

그래서 직접 prime인지 체크해봤더니 모두 false -> n에 들어가는 인수이다. 

ai의 도움을 받아 가장 큰 인수 빼고 코드를 짜보면…

from itertools import combinations
from sympy import isprime

def find_valid_p(n_factors):
    valid_p = set()
    factors = []
    for base, exp in n_factors.items():
        factors.extend([base] * exp)
    
    for r in range(1, len(factors) + 1):
        for combo in combinations(factors, r):
            p = 1
            for factor in combo:
                p *= factor
            if p % 2 == 0 and isprime(p + 1):
                valid_p.add(p)
    
    return sorted(valid_p)

n_factors = {
    2: 3, 3: 1, 5: 2, 37: 1, 1117: 1, 4029461: 1,
    1403014978139: 1, 284368748316481195117: 1
}

valid_p = find_valid_p(n_factors)
print(valid_p)

가능한 인수들을 모두 출력해준다. 

위에 넣고 p-1을 p로 바꾼 후 long_to_bytes하여 경우의 수를 모두 출력해주면, DH 플래그가 나온다. 

SWING WEB2 1주차

: 티스토리에 있던 글 백업

인터넷: TCP/IP를 사용하는 컴퓨터 연결 통신망

그중 웹(World Wide Web)은 하이퍼텍스트 구조를 활용하여 정보를 연결하고 사이트들을 거미줄처럼 엮은 인터넷이다.

WEB의 구성

1. HTTP 프로토콜: 통신을 위한 규칙

2. HTML: 하이퍼텍스트 작성을 위한 도구

3. URL: 사이트 주소

WEB의 동작 구성

  프론트엔드 백엔드
해석 위치 클라이언트 서버
문서 static dynamic
처리 방식 수동, 고정 실시간
통신 방식 단방향 양방향
제작 기술 HTML, CSS, JavaScript PHP, Java, C++ 등
프레임워크  Angular JS Bootstrap Express Laravel

제작 기술

1. HTML(프론트)

웹 언어. 태그, 속성, 내용으로 나뉜다.

폼: 프론트에서 입력받은 데이터를 한 번에 서버로 전송하는 양식

a. <form>

action  데이터를 전송할 웹 URL     
method 데이터 전송 HTTP 방식  GET 요청  흔적이 남는다 
POST 요청     
name 폼 이름    

b. : 클라이언트가 입력할 수 있는 태그 

속성 속성 값  
type text 텍스트 입력
radio 선택 목록중에 하나  
checkbox 선택 목록중에 여러개  
password 암호  
button 버튼 누르기  
reset 입력값 초기화  
submit 서버로 전송  
name 텍스트 이름
value 텍스트 입력 초기값

_c.

속성 설명
name 상자 이름
size 표시할 항목 개수
multiple 복수 선택 가능 

2. javascript(프론트)

웹 페이지를 동적으로 만듦, 인터프리터 언어

*인터프리터 언어: 컴파일 작업 거치지 않고 바로 실행하는 언어

  로 표시  
주석 // 한 줄 주석
/*(어쩌구저쩌구)*/ 여러 줄 주석  
출력 window.alert()  
document.write    
console.log()    
innerHTML    
선언 var 변수 선언+값 초기화 
let 블록 스코프 지역변수 선언+값 초기화  
const 블록 스코프 읽기 전용 상수 선언   
데이터 타입 원시 타입 boolean
null    
undefined    
number    
bigint    
string    
symbol    
객체 타입 object  

*동적 타이핑

3. PHP(백)

서버 측 스크립트 언어. PHP로 작성한 코드를 HTML 소스 내부에 삽입 -> PHP 엔진을 이용한 동적 웹페이지 생성 

장점 단점  
오픈소스+저렴 보안에 취약 원격 코드 실행
대부분 서버에서 지원 XSS  
자료구조 간편, 내장 함수 多 SQL 인젝션  
직관적->작성 코드 분량 ↓ PHP Configuration  
HTML 문서 처리에 적합 파일 시스템 공격  
  복잡한 사이트 구축 힘들다   

php 동작 원리

브라우저  웹서버 PHP 파서 데이터베이스
1. 요청 보내기 -> 2. 스크립트 실행 요청 -> 3. 데이터베이스와 연결하여 작업 수행   
  <- 5. 웹 페이지 응답  <- 4. 처리 결과 전달   
  <?php 어쩌구저쩌구 ?>  
주석 // 한 줄 주석
/* 어쩌구저쩌구 */ 여러 줄 주석  
# 한 줄 쉘 스타일 주석  
선언 $ 변수 선언
$$ 가변변수 선언 변수의 값->변수 이름  

*echo; HTML 스트링에 문자 출력

레드팀: 공격자 관점

블루팀: 방어자 관점

Attack surface/Vector: 공격 지점/경로

취약점:공격 시 활용하는 부분

PoC: 취약점을 이용해서 공격이 가능하다는 걸 증명하는 코드 

Exploit: 실제 공격 코드 

client side attack 클라이언트 겨냥한 취약점 XSS: 클라이언트를 공격해서 쿠키/세션 탈취
server side attack  서버 겨냥한 취약점  SQL 인젝션: 서버 내 데이터베이스 정보 탈취
Command 인젝션: 서버 파일 탈취, 명령어 원격 실행     

DLL injection

새내기 때 작성한 글 백업했다.


DLL (Dynamic Link Library)

주로 쓰고 기초적인 함수들을 미리 만들어서 모아둔 것을 라이브러리라고 한다. DLL은 Dynamic Link Library를 뜻하는데, 해당 라이브러리를 사용할 때만 파일을 다운하여 기능을 호출한다. 정적 링크는 함수를 복사해서 붙여넣기라고 생각하고 동적 링크는 잠깐 위치를 옮겨서 호출받았다가 원함수로 돌아오는 거라고 이해했다. DLL은 메모리에 로드되면 DllMain을 실행한다.

DllMain()은 진입점 함수이다. 진입점 함수란 프로그램이 처음 시작될 때 호출되는 함수이다. DllMain 함수는 세 개의 인자를 가진다. hModule, fdwReason, IpReserved이다. hModule은 DLL 파일 이미지가 매핑된 가상 메모리 주소값이다.

DLL 인젝션이란 말 그대로 특정 프로세스에 DLL을 삽입하는 것이다. DLL을 프로세스에 삽입하면 DllMain이 실행되면서 이때 목적에 따라 코드를 넣어 프로그램이 진행될 수 있다.

DLL 인젝션 활용 예시

DLL 인젝션은 다음과 같은 경우에서 활용할 수 있다.

기능 개선 및 버그 패치: 프로그램의 소스 코드가 없는 등 수정할 수 없는 경우에 DLL 인젝션을 이용해서 새로운 기능을 추가하거나 코드, 데이터를 수정할 수 있다.

메시지 후킹: 등록된 후킹 DLL을 OS에서 직접 인젝션시켜준다.(메시지 후킹에 관해서는 아래서 자세히 서술했다.)

API 후킹: API 후킹이란 Win32 API가 호출될 때 중간에서 이를 가로채서 제어권을 얻어내는 것이다. Win32 API는 Windows에서 제공하는 API인데 원래 Windows OS는 프로그램이 시스템 자원에 접근할 수 없다. 하지만 시스템 접근이 필요할 때 이 API를 이용해서 시스템 커널에 접근을 요청한다. 후킹 함수를 DLL 형태로 만들고 인젝션하여 활용할 수 있다.

기타 응용 프로그램: PC 사용자를 감시/관리 하는 프로그램 목적으로도 쓰인다. 실행 차단, 유해사이트 접속 차단, 모니터링 프로그램 등이 있다.

악성코드: 정상적인 프로세스에 들어가서 백도어 포트를 열고 외부에서 접속하거나, 키로깅 기능 등으로 개인 정보를 훔치는 등 사용하고 있다.

DLL 인젝션 - 원격 스레드 생성 이용

다음은 블로그에서 발췌한 소스코드이다. 먼저 주석까지 그대로 작성했다. 인젝션 과정에 대해서는 코드 아래서 설명했고 그 외 세부적으로 이해가 안 되는 함수 등은 용어 정리 또는 소스 코드 안에 ///를 기입하고 작성하였다.

Myhack.cpp

// Myhack.cpp
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
BOOL Go_Injection(DWORD dwPID, LPCSTR DllPath) {
    //프로세스 핸들
    HANDLE hProcess = NULL;
    //스레드 핸들
    HANDLE hThread = NULL;
    //모듈 핸들
    HMODULE hMod = NULL;
    //DLL 경로를 기록한 메모리 주소를 넣을 포인터변수
    LPVOID pRemoteBuf = NULL;
    //스레드 시작 루틴 함수주소를 저장할 변수
    LPTHREAD_START_ROUTINE pThreadProc;
    //인젝션 할 프로세스 제어권 얻기
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
    printf(" [+] 프로세스의 핸들(hProcess) : %d\n", hProcess);
    //DLL경로의 길이 얻기
    DWORD dwBufSize = (DWORD)(strlen(DllPath) + 1);
    printf(" [+] DLL의 길이 : %d byte\n", dwBufSize);
    //인젝션 할 DLL 경로를 해당 프로세스에 기록
    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READONLY);
    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)DllPath, dwBufSize, NULL);
    printf(" [+] 인젝션할 프로세스 내 할당받은 메모리주소 : 0x%p\n", pRemoteBuf);
    printf(" [+] 할당받은 주소에 작성할 DLL의 경로 : %s\n", DllPath);
    //write한 DLL을 프로세스에서 로드하기 위한 작업
    hMod = GetModuleHandleA("kernel32.dll");
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryA");
    printf(" [+] 스레드의 시작주소(LoadLibrary) : 0x%p\n", pThreadProc);
    //write한 DLL을 인젝션할 프로세스에 스레드 생성 후 스레드의 시작주소로
    //LoadLibraryA를 지정
    hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
    printf(" [+] 인젝션한 프로세스에서 실행한 스레드 식별자 : %d\n", hThread);
    //스레드가 실행될 때까지 무한정 대기
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    CloseHandle(hProcess);
    return 1;
}

int main(int argc, CHAR *argv[]) {
    if (argc != 3) {
        printf(" [-] Usage : %s [Process_Name] [DLL_Path] \n", argv[0]);
        //argv[0]=인젝션시킬프로그램, argv[1]=인젝션할 프로세스 이름, argv[2]=dll경로
        return 0;
    }
    //PID=-1
    DWORD dwPID = 0xFFFFFFFF;
    HWND hWnd = FindWindowA(NULL, argv[1]);
    printf(" [+] 프로세스의 창 번호(hWnd) : %d\n", dwPID);
    //Go_Injection 함수의 인자로 PID와 DLL의 경로를 넘겨줌
    //Go_Injection함수 정상동작 시 TRUE 반환
    BOOL flag = Go_Injection(dwPID, argv[2]);
    return 0;
}

Injection.dll

// Injection.dll (daum.net 창이 열리는 dll파일)
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <urlmon.h>
#pragma comment(lib, "urlmon.lib")
#define DEF_DAUM_ADDR "https://daum.net/index.html"
#define DEF_SAVE_PATH "C:\\Users\\0_0\\Desktop\\index.html"

DWORD WINAPI ThreadProc(LPVOID lParam) {
    URLDownloadToFileA(NULL, DEF_DAUM_ADDR, DEF_SAVE_PATH, 0, NULL);
    MessageBoxA(NULL, " [+] Success", "caption", MB_OK);
    return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    HANDLE hThread = NULL;
    switch (fdwReason) {
        case DLL_PROCESS_ATTACH:
            hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
            //스레드를 생성하고 스레드의 시작주소를 THreadProc으로 지정 후 실행
            CloseHandle(hThread);
            break;
    }
    return TRUE;
}

인젝션 과정 설명

OpenProcess를 이용하여 대상 프로세스의 핸들 구하기:

인젝션을 하기 위해 핸들을 얻어야 한다. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); OpenProcess는 PID를 통해 핸들을 얻어올 때 사용한다. 위 코드를 해석하자면 PROCESS_ALL_ACCESS(접근권한)의 myhack.dll(dwPID) 핸들을 구한다. hProcess를 이용하여 제어할 수 있다.

VirtualAllocEx로 대상 프로세스의 메모리 공간 확보하기:

DLL 경로를 작성하기 위해 버퍼*를 할당해줘야 한다. 이때 절대경로의 문자열 길이만큼 할당해줘야 한다. pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READONLY); dwBufSIze는 경로 문자열 길이(NULL 포함)이다. VirtualAllocEx는 가상 주소 공간 내에서 메모리 상태를 변경, 할당, 해제하는 함수이다. VirtualAllocEx()의 리턴값은 할당된 버퍼의 주소이다.

WriteProcessMemory로 대상 프로세스의 메모리에 Injection 할 DLL의 경로 입력:

이후 다음을 이용하여 절대경로를 작성해준다. WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)DllPath, dwBufSize, NULL); 위 코드를 그대로 해석하면 hProcess 권한을 가지고 pRemoteBuf에 DllPath(DLL 경로 문자열)을 써준다는 뜻이다.

LoadLibrary API 주소 구하기 (GetModuleHandle, GetProcAddress):

LoadLibaryW() API를 실행시켜 myhack.dll을 호출해야 하는데 LoadLibaryA는 kernel32.dll 안에 존재한다. 때문에 kernel32.dll에서 LoadlibraryA의 api 주소를 얻어낸다. hMod = GetModuleHandleA(“kernel32.dll”); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, “LoadLibraryA”);

pThreadProc = 프로세스 메모리 내의 LoadLibraryW() 주소

pRemoteBuf = 프로세스 메모리 내의 “C:\myhack.dll” 주소

CreateRemoteThread로 대상 프로세스의 Injection된 데이터 실행하기:

LoadLibrary()를 실행하면 DLL이 인젝션할 프로세스 메모리 안으로 삽입된다. 삽입되면 DllMain()이 호출되고 이는 공격자가 원하는 행위를 프로세스 내에서 실행할 수 있다는 뜻이다. hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);

pThreadProc = 프로세스 메모리 내의 LibraryA() 주소

pRemoteBuf = 프로세스 메모리 내의 삽입할 DLL 파일 경로 문자열 주소

CreateRemoteThread()
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess, //프로세스 핸들
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress, //스레드 함수 시작
__in LPVOID lpParameter, //스레드 파라미터 주소
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId //)

CreateRemoteThread 함수는 가상 주소 공간에 실행되는 스레드를 생성한다. 프로세스 핸들을 가져야 한다. lpThreadAttributes는 하위 프로세스가 반환된 핸들을 상속할 수 있는지에 대한 여부를 나타내는 포인터이다. 본래 소스코드에서 NULL로 입력해줬으므로 스레드는 핸들을 상속할 수 없다. lpThreadId는 스레드 식별자를 수신하는 변수에 대한 포인터이다. 본 코드에서 NULL로 입력해줬으므로 스레드 식별자는 반환되지 않는다.

DLL injection – 레지스트리 이용

Windows 운영체제에서 제공하는 Applnit_DLLs와 LoadApplnit_DLLs라는 레지스트리* 항목이 있다. Applnit_DLLs 항목에 인젝션을 원하는 DLL 경로 문자열을 쓰고 LoadApplnit_DLLs 항목의 값을 1로 변경한 후 재부팅하면, 모든 프로세스에 해당 DLL을 삽입한다.

Myhack2.cpp

#include "windows.h"
#include "tchar.h"
#define DEF_CMD L"c:\\Program files\\Internet Explorer\\iexplore.exe"
#define DEF_ADDR L"http://www.naver.com"
#define DEF_DST_PROC L"notepad.exe"

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    TCHAR szCmd[MAX_PATH] = {0,};
    TCHAR szPath[MAX_PATH] = {0,};
    TCHAR *p = NULL;
    STARTUPINFO si = {0,};
    PROCESS_INFORMATION pi = {0,};
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;

    switch( fdwReason ) {
        case DLL_PROCESS_ATTACH :
            //로딩한 프로세스 정보 일치하는지 확인
            if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
                break;
            if( !(p = _tcsrchr(szPath, '\\')) )
                break;
            if( _tcsicmp(p+1, DEF_DST_PROC) )
                break;
            wsprintf(szCmd, L"%s %s", DEF_CMD, DEF_ADDR);
            if( !CreateProcess(NULL, (LPTSTR)(LPCTSTR)szCmd,
                               NULL, NULL, FALSE,
                               NORMAL_PRIORITY_CLASS,
                               NULL, NULL, &si, &pi) )
                break;
            if(pi.hProcess != NULL )
                CloseHandle(pi.hProcess);
            break;
    }
    return TRUE;
}

인젝션 과정

IE를 숨김 모드(SW_HIDE)로 실행한다. cmd에서 레지스트리 에디터를 실행한다.

Applnit_DLLs로 이동한다. (경로:Mycomputer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows)

Applnit_DLLs의 값을 삽입할 DLL 경로로 변경한다.

LoadApplnit_DLLs의 값을 1로 입력한다.

재부팅한다.

프로세스 익스플로러에서 인젝션이 되었는지 확인한다.

DLL injection – 메시지 후킹

후킹은 정보를 염탐하거나 조작하는 행위를 말한다. Windows OS에서 키보드로 입력하고 마우스로 선택, 이동 등의 행위는 모두 이벤트이다. 이벤트가 발생할 때 OS는 이미 정의된 메시지를 프로그램으로 통보한다. SetWindowsHookEx()를 이용하여 메시지 훅을 설치하면 운영체제에서 hook procedure을 담고 있는 DLL을 프로세스에게 강제로 삽입시킨다. 다음은 블로그에서 발췌한 소스코드이다. 먼저 주석까지 그대로 작성했다. 후킹 과정에 대해서는 코드 아래서 설명했고 그외 세부적으로 이해가 안 되는 함수 등은 용어 정리 또는 소스 코드 안에 ///를 기입하고 작성하였다.

HookMain cpp

#include "stdio.h"
#include "conio.h"
#include "windows.h"
#define DEF_DLL_NAME "KeyHook.dll"
#define DEF_HOOKSTART "HookStart"
#define DEF_HOOKSTOP "HookStop"
typedef void(*PFN_HOOKSTART)();
typedef void(*PFN_HOOKSTOP)();
void main() {
    HMODULE hDll = NULL;
    PFN_HOOKSTART HookStart = NULL;
    PFN_HOOKSTOP HookStop = NULL;
    char ch = 0;
    //KeyHook.dll 로딩
    hDll = LoadLibraryA(DEF_DLL_NAME);
    //export 함수 주소 얻기
    HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);
    HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);
    //후킹시작
    HookStart();
    //사용자가 ‘q’를 입력할 때까지 대기
    printf("press 'q' to quit!\n");
    while( _getch() != 'q' );
    //후킹종료
    HookStop();
    //KeyHook.dll 언로딩
    FreeLibrary(hDll);
}

KeyHook.cpp

#include "stdio.h"
#include "windows.h"
#define DEF_PROCESS_NAME "notepad.exe"
HINSTANCE g_hinstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID IpvReserved) {
    switch( dwReason ) {
        case DLL_PROCESS_ATTACH:
            g_hInstance = hinstDLL;
            break;
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    char szPath[MAX_PATH] = {0, };
    char *p = NULL;
    if( nCode >= 0 ) {
        //bit 31: 0 = key press, 1= key release
        if( !(lParam & 0x900000000) ) //키보드가 눌렀다 떨어질 때
        {
            GetModuleFileNameA(NULL, szPath, MAX_PATH);
            p = strrchr(szPath, '\\');
            //현재 프로세스 이름을 비교해서 notepad.exe라면, 메시지는 응용 프로그램(혹은 다음
            //훅)으로 전달되지 않음
            if( !_stricmp(p+1, DEF_PROCESS_NAME) )
                return 1;
        }
    }
    //일반적인 경우에는 CallNextHookEx()을 호출하여 응용 프로그램(혹은 다음 훅)으로 메시지
    //를 전달
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
#ifdef __cplusplus
extern "C" {
#endif
    __declspec(dllexport) void HookStart() {
        g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
    }
    __declspec(dllexport) void HookStop() {
        if( g_hHook ) {
            UnhookWindowsHookEx(g_hHook);
            g_hHook = NULL;
        }
    }
#ifdef __cplusplus
}
#endif

후킹 과정

HOOKSTART와 HOOKSTOP 함수의 주소를 얻는다:

GetProcAddress 함수는 특정 DLL에서 내보내기된 함수 또는 변수의 주소를 가져온다. HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART); HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);

HookStart로 후킹:

HookStart가 호출되면 SetWindowsHookEx()에 의해 키보드 훅 체인에 KeyboardProc()이 추가된다. KeyboardProc() 원형:

LRESULT CALLBACK KeyboardProc(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam //)

키보드 입력이 발생했을 때 현재 실행중 프로세스 이름과 “notepad.exe” 문자열과 비교하여 같다면 1을 반환하고 KeyboardProc() 함수를 종료시킨다. 이 부분이 메시지를 가로채서 없애는 동작이다.(후킹) 또 return CallNextHookEx(g_hHook, nCode, wParam, lParam); 명령을 실행하면 메시지는 다른 프로그램이나 다른 훅 함수로 전달된다.(후킹)

사용자로부터 키보드 입력 발생

OS는 키보드 입력이 발생한 해당 프로세스에 KeyHook.dll 인젝션

그 후 다시 키보드 입력이 발생하면 SetWindowsHookEx() 대신 KeyboardProc() 먼저 호출

용어 정리

백도어 포트: 공격자가 특정 컴퓨터에 침입하고 원할 때 재침입할 수 있게 만들어놓은 포트

키로깅: 키보드로 입력하는 정보를 중간에서 훅/후킹하는 해킹 도구

버퍼: 임시 저장 공간/ 가상 공간

레지스트리: 윈도우 시스템에서 사용하는 데이터베이스. 프로세스 종류, 주기억장치의 용량, 주변장치 정보 등 시스템 구성 정보가 담겨있다.

느낀 점

멘토님 피드백을 받고 이대로 공부 느낌을 살릴지, 칼럼적으로 파고들지 고민을 많이 했는데 일단 공부 목적을 살리기로 했다. 사실 인젝션에서 최신 동향 조사가 제대로 안됐고 프롬프트 인젝션은 내가 지향하는 해킹 기술 공부와는 거리가 멀어보였다. 그래서 그냥 다양한 인젝션을 알아보는 방향으로 정했다. 내가 궁금해서 찾는 경우가 많아서 조사도 실습도 즐겁게 진행할 수 있었지만, 내가 얼마나 서칭하냐에 따라 스터디 역량이 크게 바뀌는 것 같다. 이번 주제가 이미 정의되어 있는 함수에 대한 지식이 부족해서 공부가 어려웠다. 사실 DLL 인젝션이 잘 설명되어 있는 책이 하나인건지 찾는 국내 블로그마다 실습이 똑같았는데 그럼에도 모르는 부분이 많아서 이해하기까지 오래 걸렸고 이해못하고 넘어간 부분도 있는 거 같아 아쉽다. 또, 분량 조절을 못해서 생각보다 오래 걸렸다… 다음부턴 미리미리 시작해서 제시간에 제출해야겠다…

+) 3학년 되고 보니까 어째 이때보다 공부를 안 하는 느낌이다. 분발하자 ㅋㅎ

다음 뉴스 스터디 방향

Reflective Dll injection에 대해 찾아보고 오늘 찾은 DLL injection과 비교해볼 예정이다.

참고자료

DLL이란? (Dynamic Link Library) . (n.d.). https://goddaehee.tistory.com/185.

[전지적해커시점] DLL Injection . (n.d.). https://ccurity.tistory.com/392.

악성코드로 알아보는 Reflective DLL Injection . (n.d.). https://www.igloo.co.kr/security-information/%EC%95%85%EC%84%B1%EC%BD%94%EB%93%9C%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-reflective-dll-injection/.

03-03. DLL Injection . (n.d.). https://fistki.tistory.com/6.

DLL Injection - Remote Thread 생성 & 레지스트리 이용 . (n.d.). https://leeeeye321.tistory.com/262.

[리눅스 핵심 원리] 23장, DLL 인젝션 . (n.d.). https://dyoerr9030.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-23%EC%9E%A5-DLL-%EC%9D%B8%EC%A0%9D%EC%85%98.

API 후킹(API Hooking) . (n.d.). https://velog.io/@dnrgus1127/API-%ED%9B%84%ED%82%B9API-Hooking#:~:text=%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%97%90%20%EB%A1%9C%EB%94%A9%EB%90%98%EC%96%B4,%EB%84%90%EB%A6%AC%20%EC%82%AC%EC%9A%A9%EB%90%98%EA%B3%A0%20%EC%9E%88%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%B4%EB%8B%A4.&text=DLL%20%EC%9D%98%20Export%20Address%20Table,%EB%A1%9C%20%EB%B3%80%EA%B2%BD%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%B4%EB%8B%A4..

DLL의 진입점 함수 . (n.d.). https://makersweb.net/windows/2019.

DLL의 진입점 함수 . (n.d.). http://egloos.zum.com/sweeper/v/2991972.

[MFC] OpenProcess 함수에 대하여! . (n.d.). https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=rjseorl95&logNo=221481732607.

VirtualAllocEx 함수 . (n.d.). https://majg.tistory.com/33.

CreateRemoteThread 함수 . (n.d.). https://majg.tistory.com/37.

23장 DLL 인젝션 . (n.d.). https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ilikebigmac&logNo=221470036755.

리버싱 핵심원리_21_Windows 메시지 후킹 . (n.d.). https://chive0402.tistory.com/10.

GetProcAddress 함수 . (n.d.). https://majg.tistory.com/36.

[리버싱 핵심원리] DLL injection 예제 코드 해설 . (n.d.). https://cyalume.tistory.com/39.

DLL 인젝션 . (n.d.). https://m.blog.naver.com/ster098/221813393324.

윈도우 ] 레지스트리란? . (n.d.). https://m.blog.naver.com/rbdi3222/220597850076.

백도어의 정의, 기능, 종류 . (n.d.). https://m.blog.naver.com/nologout/17542883.

키로깅(Key Logging)프로그램 이란? . (n.d.). https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=n_privacy&logNo=80203247739.

[개념정리] 버퍼(BUFFER)란? 버퍼 개념 . (n.d.). https://dololak.tistory.com/84.