Thursday, August 1, 2013

Win32 API 를 이용한 File Copy

 Win32 API 만을 이용해서
시스템 폴더에 있는 cmd.exe 화일을 c:\ 에 다른 이름으로 copy 를 해보자
(API중 CopyFile 및 MoveFile 사용하지 않고)

먼저 순서를 생각하고 관련된 API를 생각해보자

첫번째 Copy를 하려면 대상을 메모리로 올려야 하므로 cmd.exe 를 열어야 한다.
두번째 동일한 사이즈로 카피를 하려면 사이즈를 check 해야 한다.
세번째 읽은 내용을 메모리에 저장을 해야 한다.
네번째 메모리에 저장한 내용을 원하는 화일로 지정한 사이즈 만큼 저장한다.
마지막으로 열었던 화일핸들을 닫아 주면 된다.

OllyDBG 의 win32help 화일을 이용해도 좋고, MSDN의 Library 검색을 이용해도 된다.
관련된 함수를 좀 살펴보면,

HANDLE WINAPI CreateFile(
  _In_      LPCTSTR lpFileName,
  _In_      DWORD dwDesiredAccess,
  _In_      DWORD dwShareMode,
  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_      DWORD dwCreationDisposition,
  _In_      DWORD dwFlagsAndAttributes,
  _In_opt_  HANDLE hTemplateFile
);
첫번째 인자로 화일이름이 저장된 포인터, 문자열은 바로 메모리에 저장된 순간
포인터가 반환되므로 문자열을 그대로 사용해도 무방하다.
두번째 인자로 엑세스 방법인데 읽어 들여야 하므로 GENERIC_READ 가 사용된다.
(MSDN 을 꼭 참고하기 바란다)

DWORD WINAPI GetFileSize(
  _In_       HANDLE hFile,
  _Out_opt_  LPDWORD lpFileSizeHigh
);
화일의 크기를 반환받는 API 인데 사용법이 간단하다. 첫번째 인자로
화일 핸들만 넘겨주면 사이즈가 반환된다. 두번째는 반환되는 부분으로 만약 화일 사이즈가
4바이트를 넘어갈경우에 상위 4바이트를 사용해야 하는데 필요할 경우 사용이 된다.

핸들의 개념을 잠깐 설명하면
윈도우에서는 각각의 응용프로그램이 OS 자원에 직접 접근할 수가 없다.
따라서 OS가 각각의 응용프로그램이 접근해서 사용할 수 있도록 자원에 일련의
고유 ID를 붙여 놓았는데 그것을 핸들이라고 생각하면 된다.

BOOL WINAPI ReadFile(
  _In_         HANDLE hFile,
  _Out_        LPVOID lpBuffer,
  _In_         DWORD nNumberOfBytesToRead,
  _Out_opt_    LPDWORD lpNumberOfBytesRead,
  _Inout_opt_  LPOVERLAPPED lpOverlapped
);
첫번째 인자로 화일핸들과 세번째 인자로 GetFileSize 로 알아낸 사이즈를 넘겨주면 된다.
WriteFile 도 사용법이 동일하다.
마지막엔 CloseHandle 로 사용한 자원의 Handle 을 닫아 주어야 한다.

전체 적인 Coding 을 해보자.

==========================================================

#include <windows.h>

#define PATH     "C:\\windows\\system32\\cmd.exe"
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPre, LPSTR lpCmd, int nshow){
    HANDLE hFile;
    DWORD dwFileSize;
    DWORD dwRead;
    char str[500000]="0";

    //CreateFile 함수를 이용해서 화일의 핸들을 반환받고
    hFile = CreateFile(PATH, GENERIC_READ,0,NULL, OPEN_ALWAYS,            
                              FILE_ATTRIBUTE_NORMAL, NULL);

    //GetFileSize 함수를 이용해서 화일의 크기를 반환받아서
    dwFileSize = GetFileSize(hFile, NULL);

    //사이즈만큼 ReadFile을 이용해서 str 배열안으로 읽어들인다.
    ReadFile(hFile, str, dwFileSize, &dwRead, NULL);

    //화일 핸들을 닫아주고
    CloseHandle(hFile);

    //복사할 위치에 화일을 생성후 핸들을 돌려 받는다.
    hFile = CreateFile("C:\\cmd.exe", GENERIC_WRITE,0,NULL, CREATE_ALWAYS, 
                              FILE_ATTRIBUTE_NORMAL, NULL);

    //생성된 화일에 str 을 써 넣는다.
    WriteFile(hFile, str, dwFileSize, &dwRead, NULL);

    //핸들을 닫아준다.
    CloseHandle(hFile);
==========================================================
















No comments:

Post a Comment