일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |
- codeengn basic rce 01
- bob
- Best of the Best
- 사회적 사실
- 논문리뷰
- CodeEngn Basic 01
- CodeEngn
- 사회분업론
- 디지털 포렌식 트랙
- malware
- 에밀 뒤르켐
- 코드엔진
- 코드엔진 베이직
- 철학
- CodeEngn Basic 5
- BoB 12기 최종합격 후기
- BoB 12기
- 자살론
- 리버싱
- h4ckinggame
- 코드엔진 basic 5
- Today
- Total
woonadz :)
WIN32 API 프로그래밍 - 폴더 내 모든 파일 출력하기(FindFirstFileA, FindNextFileA) 본문
WIN32 API 프로그래밍 - 폴더 내 모든 파일 출력하기(FindFirstFileA, FindNextFileA)
C_scorch 2023. 10. 26. 01:07FindFirstFileA 함수
HANDLE FindFirstFileA(
[in] LPCSTR lpFileName,
[out] LPWIN32_FIND_DATAA lpFindFileData
);
[in] lpFileName
디렉터리 또는 경로 및 파일 이름입니다. 파일 이름에는 와일드카드 문자(예: 별표(*) 또는 물음표(?)가 포함될 수 있습니다. 이 매개 변수는 NULL, 잘못된 문자열(예: 빈 문자열 또는 종료 null 문자가 없는 문자열) 또는 후행 백슬래시(\)로 끝나서는 안 됩니다.
문자열이 와일드카드, 마침표(.) 또는 디렉터리 이름으로 끝나는 경우 사용자는 경로의 루트 및 모든 하위 디렉터리에 대한 액세스 권한이 있어야 합니다.
⇒ 파일 목록을 검사하고 싶은 폴더 경로를 지정해줍니다.
[out] lpFindFileData
찾은 파일 또는 디렉터리에 대한 정보를 수신하는 WIN32_FIND_DATA 구조체에 대한 포인터입니다.
⇒ 파일 정보를 저장할 수 있도록 지정해줍니다.
반환 값
함수가 성공하면 반환 값은 FindNextFile 또는 FindClose에 대한 후속 호출에 사용되는 검색 핸들이며 lpFindFileData 매개 변수에는 발견된 첫 번째 파일 또는 디렉터리에 대한 정보가 포함됩니다.
함수가 lpFileName 매개 변수의 검색 문자열에서 파일을 찾지 못하거나 실패하면 반환 값이 INVALID_HANDLE_VALUElpFindFileData 의 내용이 확정되지 않습니다. 확장 오류 정보를 가져오려면 GetLastError 함수를 호출합니다.
일치하는 파일을 찾을 수 없어 함수가 실패하면 GetLastError 함수는 ERROR_FILE_NOT_FOUND 반환합니다.
⇒ HANDLE 값을 반환값으로 받기 때문에 HANDLE 구조체로 변수를 선언합니다.
#include <stdio.h>
#include <Windows.h>
#include <fileapi.h>
int main(void) {
LPCSTR folder_path = "C:\\\\Users\\\\Owner\\\\Documents\\\\test\\\\*"; //파일 리스트를 찾을 폴더명
WIN32_FIND_DATAA file_list;
HANDLE result_handle;
result_handle = FindFirstFileA(folder_path,&file_list);
if (result_handle != INVALID_HANDLE_VALUE) { //FineFirstFileA 함수가 성공했을 때
printf("%s", file_list.cFileName); //첫번째 파일명을 출력
}
else { //FineFirstFileA 함수가 실패했을 때
printf("첫번째 파일 찾기에 실패하였습니다.");
}
return 0;
}
LPWIN32_FIND_DATAA 는 WIN32_FIND_DATAA 구조체의 포인터입니다.
저는 구조체 형식이 더 익숙해서 WIN32_FIND_DATAA 로 변수 선언을 해주었습니다.
WIN32_FINE_DATAA 의 멤버들을 아래에서 확인할 수 있습니다. 위 코드에서는 FileName만 필요하기 때문에 그 값만 가져왔습니다.
typedef struct _WIN32_FIND_DATAA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
CHAR cFileName[MAX_PATH];
CHAR cAlternateFileName[14];
DWORD dwFileType; // Obsolete. Do not use.
DWORD dwCreatorType; // Obsolete. Do not use
WORD wFinderFlags; // Obsolete. Do not use
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
"C:\\Users\\Owner\\Documents\\test\\*" 위 사진은 탐색하려던 폴더에 있는 파일들입니다. 하지만 실제 출력값은 “.” 만 확인할 수 있었습니다. 그 이유는 FindFirstFileA 함수는 “.”과 “..”의 경로까지 포함하여 출력을 하기 때문에 가장 첫번째 파일로 “.”이 출력된 것 입니다.
다음 코드에서는 “.”과 “..” 경로를 예외처리하고 FindNextFileA 함수를 이용하여 폴더 내에 있는 모든 폴더와 파일들을 출력해보겠습니다.
FindNextFileA 함수
BOOL FindNextFileA(
[in] HANDLE hFindFile,
[out] LPWIN32_FIND_DATAA lpFindFileData
);
[in] hFindFile
FindFirstFile 또는 FindFirstFileEx 함수에 대한 이전 호출에서 반환된 검색 핸들입니다.
⇒ 저는 FindFirstFile을 이용하여 첫번째 파일의 정보를 불러왔습니다.
[out] lpFindFileData
찾은 파일 또는 하위 디렉터리에 대한 정보를 수신하는 WIN32_FIND_DATA 구조체에 대한 포인터입니다.
⇒ FindFirstFile의 output과 같은 형식입니다.
반환값
함수가 성공하면 반환 값이 0이 아니고 lpFindFileData 매개 변수에 찾은 다음 파일 또는 디렉터리에 대한 정보가 포함됩니다.
함수가 실패하면 반환 값은 0이고 lpFindFileData 의 내용은 확정되지 않습니다. 확장 오류 정보를 가져오려면 GetLastError 함수를 호출합니다.
일치하는 파일을 더 이상 찾을 수 없으므로 함수가 실패하면 GetLastError 함수는 ERROR_NO_MORE_FILES 반환합니다.
⇒ 반환값이 0인지 여부에 따라 함수의 성공 여부가 달라집니다.
#include <stdio.h>
#include <Windows.h>
#include <fileapi.h>
#include <string.h>
int main(void) {
LPCSTR folder_path = "C:\\\\Users\\\\Owner\\\\Documents\\\\test\\\\*"; //파일 리스트를 찾을 폴더명
WIN32_FIND_DATAA file_list;
HANDLE result_handle;
result_handle = FindFirstFileA(folder_path,&file_list);
while (1){
if (result_handle != INVALID_HANDLE_VALUE) { //FindFirstFileA 함수가 성공했을 때
if (strcmp(file_list.cFileName, ".") != 0 && strcmp(file_list.cFileName, "..") != 0) { //"." 경로와 ".." 경로 예외처리
printf("%s\\n", file_list.cFileName);
}
if (!FindNextFileA(result_handle, &file_list)) { //FindNextFileA 함수를 실행시키고 실패했을 때(모든 파일 목록을 찾았을 때)
printf("모든 파일 목록을 찾았습니다.");
break;
}
}
else { //FindFirstFileA 함수가 실패했을 때
printf("첫번째 파일 찾기에 실패하였습니다.");
break;
}
}
return 0;
}
다음 코드에서는 폴더를 출력하지 않고 폴더 안에 있는 파일들까지 출력하는 코드를 만들어보겠습니다.
#include <stdio.h>
#include <Windows.h>
#include <fileapi.h>
#include <string.h>
#define MAX_PATH 1000
void all_file_list(char* path);
int main(void) {
char *root_path = "C:\\\\Users\\\\Owner\\\\Documents\\\\test";
all_file_list(root_path);
printf("모든 파일 목록을 찾았습니다.");
return 0;
}
void all_file_list(char* path) {
char folder_path[MAX_PATH];
WIN32_FIND_DATAA file_list;
HANDLE result_handle;
strcpy_s(folder_path, sizeof(folder_path), path);
strcat_s(folder_path, sizeof(folder_path), "\\\\*");
result_handle = FindFirstFileA(folder_path, &file_list);
while (1) {
if (result_handle != INVALID_HANDLE_VALUE) {
if (strcmp(file_list.cFileName, ".") != 0 && strcmp(file_list.cFileName, "..") != 0) {
if (file_list.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { //만약 폴더라면
char tmp_path[MAX_PATH];
WIN32_FIND_DATAA tmp_file_list;
strcpy_s(tmp_path, sizeof(tmp_path), path);
strcat_s(tmp_path, sizeof(tmp_path), "\\\\");
strcat_s(tmp_path, sizeof(tmp_path), file_list.cFileName);
all_file_list(tmp_path); //재귀함수를 통해 자식 폴더의 파일들까지 모두 출력
}
else {
printf("%s\\n", file_list.cFileName);
}
}
if (!FindNextFileA(result_handle, &file_list)) {
break;
}
}
else {
printf("첫번째 파일 찾기에 실패하였습니다.");
break;
}
}
}
간단하게 재귀함수를 이용하여 루트 폴더 내에 있는 모든 파일들을 출력하는 코드를 만들 수 있었습니다.
랜섬웨어는 이런식으로 파일 탐색을 하여 파일을 하나 하나 암호화하는 동작을 수행할 것 입니다. 다만, 걱정되는 부분이 재귀함수를 이용하여 시간 복잡도가 높아졌습니다. 만약 악성코드 개발자라면 랜섬웨어가 빠른 시간 내에 파일을 암호화하는 것을 중요하게 생각할 것 같습니다. 그래서 다른 탐색 알고리즘을 사용하여 시간 복잡도를 줄여보는 것도 좋을 것 같습니다.
'IT > malware dev' 카테고리의 다른 글
WIN32 API 프로그래밍 - CMD를 이용한 자가 삭제 (1) | 2023.11.03 |
---|---|
WIN32 API 프로그래밍 - 특정 파일 암호화 및 확장자 변경하기: 지금까지의 코드 병합 (1) | 2023.11.01 |
WIN32 API 프로그래밍 - 특정 파일 XOR 암호화하기(2):암호화된 데이터 새로운 확장자로 저장하기 (WriteFile) (1) | 2023.10.31 |
WIN32 API 프로그래밍 - 특정 파일 XOR 암호화하기(1):파일 데이터 불러와서 암호화하기 (CreateFileA, ReadFile) (1) | 2023.10.30 |
WIN32 API 프로그래밍 - 폴더 경로 가져오기(SHGetKnownFolderPath) (0) | 2023.10.25 |