KH 실전모의면접 


피드백> 호흡 조절 -> PT 경험하기


1. 1분자기소개 

2. 자신의 장단점 


1. Flag의 6가지

- URG(긴급), ACK(승인), PSH(밀어넣기), RST(초기화), SYN(동기화), FIN(종료)


2. DOS의 종류

- TCP Syn flooding Attack

   : TCP 연결 설정 과정 중에 3Way-Handshaking 과정에서 Half-Open 연결 시도가 가능하다는 취약점을 이용 

- SMURF Attack 

   : 직접적인 ICMP 브로드 캐스트와 3가지 구성요소인 공격자, 증폭 네트워크, 공격대상 서버를 이용

- Land Attack 

   : 공격자가 임의로 자신의 IP와 포트를 대상 서버의 IP 및 포트와 동일하게 하여 서버에 접속하는 공격방식

- Ping of Death 

   : 공격의 기본은 핑을 이용하여 ICMP 패킷을 정상적인 크기(65,535 bytes)보다 아주 크게 만든 것


3. AR, VR, MR의 차이점

4. AI, 딥러닝, 머신러닝의 차이점

5. L4스위치를 사용하는 이유


6. 인가와 인증의 차이

- 인증 : 주체의 신원을 검증하기 위한 것  ex) 패스워드, 생체인식, 토큰 

- 인가 : 인증된 주체에게 저근을 허용하고 권리를 부여하는 것 ex) 접근제어목록(ACL), 보안등급 


6. 악성코드의 종류

- 바이러스 : 자기복제 O

- 트로이목마 : 자기복제 X, 정상적인 프로그램에 숨어서 실행되는 것  

- 웜  : 자기복제 O, 네트워크를 통해 스스로 전파  


7. SSL이란?


8. DML, DCL, DDL 종류 


9. 스니핑과 스푸핑 차이


10. 파밍, 피싱, 스미싱의 차이 


11. 백도어에 대해 설명하시오 

- 시스템 관리자가 유지보수를 위해 만들어놓은 문이다. 정보를 탈취할 때마다 관리자 권한을 취득하는 것이 번거로우니 만들어 놓는 것. 


12. OWASP의 종류 

- SQL 인젝션

- XSS(Cross-site-Script) // 공격대상이 클라이언트, CSRF의 공격대상은 서버 

// XSS는 웹페이지에 스크립트를 삽입하는 것, CSRF는 해커가 권한있는 클라이언트인척하여 서버에 요청위조 

- 취약한 접근통제

- 취약한 인증 


13. SCAN의 종류

- TCP Connect 스캔

- TCP Half Open 스캔

- TCP ACK 스캔

- TCP FIN 스캔

- TCP Null 스캔

- Xmas 트리 스캔

- UDP 스캔 


14. APT란

15. 랜섬웨어란? 해결방안



'Soso' 카테고리의 다른 글

도메인 등록  (0) 2018.10.31
드디어  (0) 2018.10.24

1. 스택프레임

// ESP가 아닌, EBP레지스터를 사용하여 스택 내의 로컬 변수, 파라미터, 복귀 주소에 접근하는 기법. 

왜?? ESP는 수시로 변경되기 때문에 ESP를 기준으로 프로그램을 만들면 정확한 위치를 참고할 때 CPU가 힘들어. 


예시>

PUSH EBP  // 함수 시작(EBP를 사용하기 전에 기존의 값을 스택에 저장)

MOV EBP, ESP // 현재 ESP(스택 포인터)를 EBP에 저장 

......

......

MOV ESP, EBP // ESP를 정리 (함수 시작했을 때의 값으로 복원시킴)

POP EBP // 리턴되기 전에 저장해 놓았던 원래 EBP 값으로 복원

RETN  // 함수 종료 




call 02_hello.00401000 // add() 함수 



PUSH EBP // EBP값을 스택에 넣어라. EBP가 메인함수에서 베이스 포인터의 역할을 하게 되니깐 EBP가 이전에 갖고 있던 값을 스택에 백업하기 위한 용도
MOV EBP,ESP // ESP의 값을 EBP로 옮겨라. 즉, EBP는 ESP와 같은 값을 갖게됨.
SUB ESP,8 // long은 4byte이며, a,b 2개이므로 8byte의 공간 확보
MOV DWORD PTR SS:[EBP-4],1 // a의 1을 [EBP-4]에 저장.
MOV DWORD PTR SS:[EBP-8],2 // b의 2를 [EBP-8]에 저장.
MOV EAX,DWORD PTR SS:[EBP-8] // [EBP-8]주소에서 4byte 크기의 메모리 내용을 EAX로 이동
PUSH EAX // b에 값인 2를 스택에 넣기
MOV ECX,DWORD PTR SS:[EBP-4] // [EBP-4]주소에서 4byte 크기의 메모리 내용을 ECX로 이동
PUSH ECX // a에 값인 1을 스택에 넣기
CALL 02_hello.00401000 // add()함수
ADD ESP,8
PUSH EAX ; /<%d>
PUSH 02_hello.004020F4 ; |format = "%d
"
CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
ADD ESP,8 // 스택공간 정리 (파라미터 a,b관련 공간)
XOR EAX,EAX // 리턴값을 받는 EAX 초기화
MOV ESP,EBP // 함수의 에필로그
POP EBP
RETN


< CALL 02_hello.00401000 >

PUSH EBP // main() 함수에서 사용되던 EBP값을 스택에 백업
MOV EBP,ESP // add() 함수의 프롤로그
SUB ESP,8 // 스택에 8byte의 공간확보 (로컬변수 a,b의 공간)
MOV EAX,DWORD PTR SS:[EBP+8] // 파라미터 a를 가리킴
MOV DWORD PTR SS:[EBP-8],EAX // a의 값인 1을 [EBP-8]에 넣음
MOV ECX,DWORD PTR SS:[EBP+C] // 파라미터 b를 가리킴
MOV DWORD PTR SS:[EBP-4],ECX // b의 값인 2를 [EBP-4]에 넣음
MOV EAX,DWORD PTR SS:[EBP-8] // 1을 EAX에 넣음
ADD EAX,DWORD PTR SS:[EBP-4] // EAX에 2를 더해서 EAX는 3이 됨
MOV ESP,EBP // ESP를 원래대로 복원 (함수가 시작할때 ESP의 값을 EBP에 넣어두었다가 함수가 종료될 때 ESP를 원래대로 복원시키는 목적)
POP EBP





006.



#include <stdio.h>
main()
{
int i;
int hap = 0;
for( i = 1; i <= 10; i = i + 1 )
{
hap = hap + i;
}
printf( "1부터 10까지의 합: %d", hap );
}








'리버싱 > C언어 300제' 카테고리의 다른 글

리버싱 - c언어(001-005)  (0) 2018.12.13

001. c 프로그램 시작하기.

#include <stdio.h>
void main()
{
printf("안녕하세요."); // '안녕하세요' 출력
}



PUSH EBP

MOV EBP, ESP // 스택에 공간 확보

-----------------함수 프롤로그 ------------------

PUSH c_pro.004020F4 // c_pro.004020F4를 스택에 넣기

CALL DWORT PTR..... // printf함수 호출

------------------------------------------------

ADD ESP,4 // 사용한 스택없애주는 (ESP를 내리므로써 사용한 값이 들어있는 스택을 쓰레기값으로 만든다)

XOR EAX,EAX // EAX는 리턴값을 반환하는 데 사용하는 것. 메인함수의 일이 끝났으니 반환값이 들어있는 EAX를 XOR연산을 이용하여 0으로 초기화.

RETN

--------------- 함수 에필로그 --------------------



002.


#include <stdio.h>
void main()
{
int x;
int y;
int z; // 변수 생성
x = 1;
y = 2; // 변수의 값 입력
z = x + y;
printf( "%d", z ); // z의 값을 출력
}





PUSH EBP

MOV EBP,ESP // 함수의 프롤로그 SUB ESP,0C // 변수선언을 위해 스택에 공간확보 (변수가 3개이며, 스택은 4byte 간격이기에 12byte확보 위해 hex 0C를 스택에 확보) MOV DWORD PTR SS:[EBP-8],1 // [EBP-8]은 변수 x의 공간이므로, 1을 넣음 MOV DWORD PTR SS:[EBP-4],2 // [EBP-4]는 변수 y의 공간이므로, 2를 넣음. MOV EAX,DWORD PTR SS:[EBP-8] // [EBP-8]에 있는 1을 EAX에 넣음. ADD EAX,DWORD PTR SS:[EBP-4] // [EBP-4]에 있는 2를 EAX에 더함. 따라 2+1은 3 MOV DWORD PTR SS:[EBP-C],EAX // EAX에 있는 3을 [EBP-C]에 넣음. MOV ECX,DWORD PTR SS:[EBP-C] // [EBP-C]에 있는 3을 ECX에 넣음. PUSH ECX ; /<%d> // ECX에 있는 3을 스택에 넣음. PUSH c_pro.004020F4 ; |format = "%d" CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf ADD ESP,8 // printf에 사용한 스택공간 버리기 (함수의 에필로그) XOR EAX,EAX // EAX 0으로 초기화

MOV ESP,EBP // ESP를 EBP와 같은 값으로 넣음으로써, 계산에 사용된 스택공간 버리기 POP EBP // EBP 스택에서 버리기. RETN



003.


#include <stdio.h>
#define X 1
#define PI 3.141592
int main()
{
double z;
z = X + PI; // 위에서 정의한 X와 PI의 값을 더하여 저장하는 변수
printf( "%f", z ); // 더하여 저장한 값을 실수형으로 출력
}























// FLD를 하면, 지정된 데이터가 ST0에 저장되면서 empty -> vaild로 변경.



PUSH EBP MOV EBP,ESP // 함수 프롤로그 SUB ESP,8 // 변수 저장을 위해 스택에 공간 확보 FLD QWORD PTR DS:[4020F8] // 004020F8에 있는 정보 8byte를 ST0에 로드 (ST0는 empty-> valid) FSTP QWORD PTR SS:[EBP-8] // [EBP-8]에 원래 있던 데이터는 스택에서 pop하고, ST0에 있는 데이터를 EBP-8스택에 저장, 그러면 ST0는 다시 valid -> empty

SUB ESP,8 // 변수 저장을 위해 스택에 공간 확보 FLD QWORD PTR SS:[EBP-8] ; | // [EBP-8]에 있는 8byte의 데이터를 ST0에 로드 (ST는 empty -> valid) FSTP QWORD PTR SS:[ESP] ; | // ESP에 있던 기존의 내용은 스택에서 POP하고, ST0에 들어있는 8Byte에 내용을 ESP에 저장(ST0은 valid ->empty) PUSH c_pro.004020F4 ; |format = "%f" CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf ADD ESP,0C // 함수의 에필로그 XOR EAX,EAX // 리턴값 반환하는 EAX를 초기화 MOV ESP,EBP POP EBP RETN




* FLD

// 데이터를 로드



* FSTP

// 데이터를 저장 (저장시 기존내용을 POP한다)




004.



#include <stdio.h>
void main()
{
int x;
int y;
x = 10;
y = x - 5;
if( x > y )
{
printf( "x의 값이 y보다 큽니다." );
}
else
{
printf( "x의 값이 y보다 작거나 같습니다." );
}
}





PUSH EBP
MOV EBP,ESP // 함수의 프롤로그
SUB ESP,8 // 변수 선언을 위해 스택 공간 확보
MOV DWORD PTR SS:[EBP-8],0A // 10을 [EBP-8]에 저장
MOV EAX,DWORD PTR SS:[EBP-8] // [EBP-8]에 있는 10을 EAX에 저장
SUB EAX,5 // EAX=EAX-5
MOV DWORD PTR SS:[EBP-4],EAX // EAX에 있는 5를 [EBP-4]에 저장
MOV ECX,DWORD PTR SS:[EBP-8] // [EBP-8]에 있는 10을 ECX에 저장
CMP ECX,DWORD PTR SS:[EBP-4] // ECX에 있는10에서 [EBP-4]에 있는 5를 뺀다. ECX가 더 크므로 점프하지 않는다.
JLE SHORT c_pro.0040102E // 작거나 같으면 점프니깐 점프를 하지 않는다.
PUSH c_pro.004020F4 ; /format = "x의 값이 y보다 큽니다."
CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
ADD ESP,4 // 스택에 공간확보
JMP SHORT c_pro.0040103C // 무조건 0040103C로 점프하기
PUSH c_pro.0040210C ; /format = "x의 값이 y보다 작거나 같습니다."
CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
ADD ESP,4
XOR EAX,EAX // 함수 에필로그
MOV ESP,EBP
POP EBP
RETN



* CMP A, B
// A에서 B를 뺀다.
















* JLE A, B (Jump Less Equals)
// A<=B => 점프 (무조건 A기준이다.)



005.





#include <stdio.h>
void main()
{
int x;
int y;
x = 20;
y = 10;
if( x > y )
{
printf( "x의 값이 y보다 큽니다." );
}
else
{
printf( "x의 값이 y보다 작거나 같습니다.");
}
}





























PUSH EBP
MOV EBP,ESP // 함수의 프롤로그
SUB ESP,8 // 변수 선언을 위해 스택에 공간확보
MOV DWORD PTR SS:[EBP-8],14 // [EBP-8]에 14 넣기
MOV DWORD PTR SS:[EBP-4],0A // [EBP-4]에 0A넣기
MOV EAX,DWORD PTR SS:[EBP-8] // [EBP-8]에 있는 14를 EAX에 넣기
CMP EAX,DWORD PTR SS:[EBP-4] // EAX에 있는 14와 [EBP-4]에 있는 0A를 비교하기
JLE SHORT c_pro.0040102C // 작거나 같으면 점프하기. 하지만, 크기때문에 점프하지 않는다.
PUSH c_pro.004020F4 ; /format = "x의 값이 y보다 큽니다."
CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
ADD ESP,4 // 사용한 함수있는 스택공간 지우기
JMP SHORT c_pro.0040103A // 무조건 점프
PUSH c_pro.0040210C ; /format = "x의 값이 y보다 작거나 같습니다."
CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
ADD ESP,4 // 사용한 함수가 있는 스택공간 지우기
XOR EAX,EAX // EAX(리턴값)을 초기화
MOV ESP,EBP // 함수의 에필로그
POP EBP
RETN






'리버싱 > C언어 300제' 카테고리의 다른 글

리버싱 - c언어(006-010)  (0) 2018.12.24

1. 스택(Stack)

// 높은 주소 -> 낮은 주소 (스택에 값을 입력하면 ESP가 감소하고, 값을 꺼내면 ESP는 증가한다)


- 함수 내의 로컬 변수 임시 저장

- 함수 호출 시 파라미터 전달

- 복귀 주소(return address) 저장




2. abex' crackme #1 분석 



* 어셈블리 명령어 설명

- PUSH : 스택에 값을 입력

- CALL : 지정된 주소의 함수를 호출

- INC : 값을 1 증가

- DEC : 값을 1 감소

- JMP : 지정된 주소로 점프

- CMP : 주어진 두 개의 operand 비교 ( SUB와 비슷하지만, CMP는 operand의 값이 변경되지 않고, 

                                                     EFLAGS 레지스터만 변경됨.  두 operand의 값이 동일 하면 ZF=1이다.)

- JE : 조건 분기(Jump if equal), ZF=1이면 점프 



* 스택에 파라미터를 전달하는 방법

// MessageBoxA() 함수를 호출하기 전에 4번의 PUSH 명령어를 사용하여 필요한 파라미터를 역순으로 입력.



------------------------------ c 언어로 변환 ------------------------------------------------


MessageBoxA(NULL, "Make me think your HD is CD-ROM.", "abex' 1st crackme", MB_OK | MB_APPLMODAL ); 


하지만, 받는입장에서 생각하면 Stack은 FIFO이기때문에 역순이 아닌 제대로 받는 것. 


 

'리버싱 > 리버싱의 핵심원리' 카테고리의 다른 글

PE구조 헤더  (0) 2019.03.20
Reversing - 스택프레임  (0) 2018.12.26
Reversing - 바이트 오더링, IA-32 Register 기본 설명  (0) 2018.12.13
Reversing - Hello World!  (0) 2018.12.08
Reversing - 시작<기본>  (0) 2018.12.08

1. 바이트 오더링(Byte Ordering) 

// 데이터를 저장하는 방식.



1) 빅 엔디언(Big Endian) 

// 사람이 보는 것과 동일, 앞부터 순차적으로 저장.

ex) 대형 UNIX서버(RISC계열의 CPU)



2) 리틀 엔디언(Little Endian)

// 데이터를 역순으로 저장.  

- 리틀 엔디언에서 2byte(WORD), 4byte(DWORD)와 같은 멀티 바이트인 경우 역순으로 저장

- 리틀 엔디언에서 2byte 미만 , 문자열(str은 곧 char이기에)은 빅 엔디언처럼 앞부터 순차적으로 저장.  

ex) Windows 계열 Intel x86 CPU 


2. IA-32 Register 기본 설명

* 레지스터 (Register)
// CPU내부에 존재하는 다목적 저장 공간. 

* Basic program execution registers
1) General Purpose Registers(32bit - 8개)
// 범용레지스터

- EAX (Extended Accumulator Register)
// 산술, 논리 연산 수행시 사용되는 레지스터 , 함수 리턴 값에 사용(리턴 값은 EAX에 저장한 후 리턴)
   EAX - 32bit, 반 쪼개면 AX - 16bit , 또 다시 반 쪼개면 AH, AL(각 8bit)

- EBX (Extended Base Register)
// 메모리 주소를 저장하기 위한 용도의 레지스터 

- ECX (Extended Count Register)  
// 반복 명령어(for, while 등) 사용시 카운터로 사용되는 레지스터 

- EDX (Extended Data Register)
// EAX와 함께 쓰이며, 부호 확장 명령이나 큰수의 곱셉/나눗셈 연산에 사용되는 레지스터

-------------------------- 산술 연산 명령어에서 상수/변수 값의 저장 용도로 사용 -------------------------

 - ESI (Extended Source) / EDI (Extended Destination Index)
// ESI는 데이터 조작/복사 시 데이터의 주소가 저장.
   EDI는 복사할 때 목적지의 주소가 저장. 

----------------------------------- 메모리 복사에 사용 -----------------------------------------------------------

- EBP ( Extended Base Pointer) / ESP (Extended Stack Pointer)
 // ESP는 Stack의 끝 지점 주소를 가리킴, 명령어(PUSH, POP, CALL, RET)들을 직접 조작
    EBP는 Stack의 첫 시작 주소를 가리킴, 함수가 호출되었을 때 그 순간의 ESP를 저장하고 있다가 함수가 
             리턴하기 직전에 다시 ESP에 값을 되돌려줘서 스택이 깨지지 않도록 함.(Stack Frame 기법) 

----------------------------- 메모리 주소를 저장하는 포인터로 사용 ----------------------------------------


2) Segment Registers(16bit - 6개)
// CS, DS, SS, ES, FS, GS


3) Program Status and Control Register (32bit - 1개)
// EFLAGS, 종류가 많지만 기초적인 단계에서는 3가지만 알기
   Flag는 단어 그대로 깃발이 올라가면 1(TRUE/On), 내려가면 0(False/Off) 

- Zero Flag(ZF)
// 연산 명령 후에 결과 값이 0이면 -> ZF = 1 세팅

- Overflow Flag(OF)
// 부호 있는 수의 오버플로우 발생/ MSB(Most Significant Bit) 변경 시  -> 1로 세팅  

- Carry Flag(CF)
// 부호 없는 수의 오버플로가 발생했을 때 -> 1로 세팅 


4) Instruction Pointer(32bit - 1개)
// EIP 

- EIP (Instruction pointer)
// cpu가 처리할 명령어의 주소를 나타내는 레지스터,  명령어를처리 후 자동으로 그 명령어 길이만큼 EIP를 증가시킴. 







'리버싱 > 리버싱의 핵심원리' 카테고리의 다른 글

PE구조 헤더  (0) 2019.03.20
Reversing - 스택프레임  (0) 2018.12.26
Reversing - 스택(Stack), abex' crackme #1 분석  (0) 2018.12.13
Reversing - Hello World!  (0) 2018.12.08
Reversing - 시작<기본>  (0) 2018.12.08

1. CopyFile()

// 파일 그 자체를 복사 


BOOL CopyFile(

LPCTSTR lpExisitingFileName, // 복사할 원본파일 이름 

LPCTSTR lpNewFileName, // 복사하여 새로 생성될 파일의 이름 

BOOL bFailIfExists // 새로 생성될 파일이 이미 있을 경우의 동작을 지정 

);                            TRUE -> 실패를 리턴, FALSE -> 기존 파일을 덮는다. 




#include <windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
LPWSTR lpszClass=L"ApiBase";
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst=hInstance;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=(WNDPROC)WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=NULL;
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
while(GetMessage(&Message,0,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static HANDLE hFile;
TCHAR strTemp[128];
DWORD dwRead;
TCHAR strRead[MAX_PATH]; // 읽어들인 문자열을 저장할 버퍼.
switch(iMessage)
{
case WM_RBUTTONDOWN: // 마우스 오른쪽 클릭 시
hdc=GetDC(hWnd);
SetCursor(LoadCursor(NULL,IDC_WAIT));
CopyFile(L"FileInOutExx.txt",L"C:\\Documents and Settings\\hn\\My Documents\\Visual Studio 2008\\Projects\\FileInOutEx\\FileInOutExx7.txt",FALSE);
// 파일 자체를 복사하는 함수이며, 첫 번째 인자는 원본 파일 이름, 새로 만드는 파일의 경로 및 이름, 마지막 인자는 새로 생성될 파일이 이미 있을 경우 동작을 지정하는 것이다.
// FALSE일 경우, 기존 파일을 덮어쓰고 TRUE일 경우, 실패를 리턴한다.
wsprintf(strTemp, L"%s 을 %s로 복사 하였습니다.",L"FileInOutExx.txt",L"FileInOutExx7.txt");
// 서식화된 출력을 문자열 버퍼로 보내는 것. 즉, 화면에 출력하는 것이 아니라 버퍼에 출력하는 것.
TextOut(hdc,100,100,strTemp,wcslen(strTemp));
// 문자열 출력 함수 ( strTemp에 담긴 문자열을 좌표 100,100에 뿌려주는 함수, wcslen(strTemp)는 뿌리는 문자열의 길이를 지정한 것이며, hdc는,, 말그대로 hdc라네...........?
SetCursor(LoadCursor(NULL,IDC_WAIT));
ReleaseDC(hWnd,hdc);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage, wParam, lParam));
}






















// FileInOutEx.exe를 실행. 


// 마우스 우클릭



// 코드에서 지정한 경로에 가보면, FileInOutExx7.txt가 생긴 것을 볼 수 있다. 





2. CopyFileEx()

// 파일 복사의 진행량과 같은 중간과정을 확인하기 위해서 사용하는 함수 

// 콜백 함수를 등록하여 주기적으로 호출이 가능함.


BOOL CopyFile(

LPCTSTR lpExisitingFileName, // 복사할 원본파일 이름 

LPCTSTR lpNewFileName, // 복사하여 새로 생성될 파일의 이름 

LPROGRESS_ROUTINE lpProgressRoutine, // 콜백함수 주기적 호출(파일의 복사과정 볼 수 있음)

LPVOID lpData, // 콜백함수 호출 시 들어갈 인수 값 (특별한 경우 아니면 0)

LPBOOL pbCancel, // TRUE 이면 복사 중지, FALSE이면 복사 진행 (복사 진행여부)

DWORD dwCopyFlags // 파일을 복사 수행시 옵션 플래그 (특별한 경우 아니면 0) 

);


DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER TotalFileSize, // 총 파일 크기(bytes)
LARGE_INTEGER TotalBytesTransferred, // 소스 파일에서 대상 파일로 이동한 총 파일 크기(bytes)
LARGE_INTEGER StreamSize, // 현재 파일 스트림의 총 크기(bytes)
LARGE_INTEGER StreamBytesTransferred, // 소스 파일에서 대상 파일로 이동한 총 파일 스트림 크기(bytes)
DWORD dwStreamNumber, // 현재의 스트림 넘버
DWORD dwCallbackReason, // 함수 호출의 이유
HANDLE hSourceFile, // 원본 파일의 핸들
HANDLE hDestinationFile, // 대상 파일의 핸들
LPVOID lpData) // CopyFileEx 와 MoveFileWithProgress 함수 호출 시 파라미터
#include <windows.h>
#include <tchar.h>
#define _WIN32_WINNT 0x0500 // copyFileEx 사용시 필수 요소
DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamBytesTransferred,
DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData)
// CopyFileEx 와 MoveFileWithProgress 함수 실행시 사용할 수 있도록 정의된 콜백함수.
{
HDC hdc;
TCHAR str[MAX_PATH];
HWND g_hWnd='\0'; // 널값으로 초기화 (여기서 애먹음..ㅎㅎ 어디서 선언해야할까를 고민했고,, 선언했는데 디버깅 에러나서 애먹고,, 선언을 하고 널로 초기화를 하니 문제 해결!)
hdc=GetDC(g_hWnd);
wsprintf(str,L"%d 중 %d 바이트 복사중......",TotalFileSize.LowPart, TotalBytesTransferred.LowPart);
TextOut(hdc,100,100,str,wcslen(str)); // str에 담긴 문자열을 100,100 좌표에 출력
ReleaseDC(g_hWnd,hdc);
return PROGRESS_CONTINUE;
}
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
LPWSTR lpszClass=L"ApiBase";
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst=hInstance;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=(WNDPROC)WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=NULL;
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
while(GetMessage(&Message,0,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static HANDLE hFile;
TCHAR strTemp[128];
DWORD dwRead;
TCHAR strRead[MAX_PATH]; // 읽어들인 문자열을 저장할 버퍼.
switch(iMessage)
{
case WM_RBUTTONDOWN: // 마우스 오른쪽 클릭 시
hdc=GetDC(hWnd);
SetCursor(LoadCursor(NULL,IDC_WAIT));
//CopyFile(L"FileInOutExx.txt",L"C:\\Documents and Settings\\hn\\My Documents\\Visual Studio 2008\\Projects\\FileInOutEx\\FileInOutExx7.txt",FALSE);
//wsprintf(strTemp, L"%s 을 %s로 복사 하였습니다.",L"FileInOutExx.txt",L"FileInOutExx7.txt");
//TextOut(hdc,100,100,strTemp,wcslen(strTemp));
CopyFileEx(L"ulala.mp4",L"C:\\Documents and Settings\\hn\\My Documents\\Visual Studio 2008\\Projects\\FileInOutEx\\parkseungil.mp4",
LPPROGRESS_ROUTINE(CopyProgressRoutine),0,FALSE,0);
//ulala.mp4의 파일을 지정된 경로에 parkseungil.mp4로 저장시키기. 콜백함수를 주기적으로 호출하여 파일의 복사과정을 볼 수 있게 해주는게 CopyProgressRoutine이며, 자동형변환이 되지 않아
// 강제적으로 LPPROGRESS_ROUTINE()로 맞춰주었다. 또한, 이것은 복사를 진행하기위해 FALSE를 사용하였다.TRUE라면 복사를 중지한다. 3번째, 5번째의 인자는 각각 콜백함수 호출 시 인수 값과
// 복사 수행시 옵션 플래그값을 의미하며 특수한 경우가 아니라면 0을 적는다.
MessageBox(hWnd,L"파일 복사가 완료 되었습니다.",L"알림",MB_OK);
SetCursor(LoadCursor(NULL,IDC_WAIT));
ReleaseDC(hWnd,hdc);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage, wParam, lParam));
}
// ulala.mp4를 복사할 예정


// FileInOutEx.exe를 실행 -> 우클릭 -> 파일 복사

(복사되는 진행상황을 볼 수 있다)


// 지정된 경로에 parkseungil.mp4로 파일이 있는 것을 볼 수 있다.




1. 파일 공유 예제

- 파일 공유 허용범위를 지정하기 위해선 CreateFile() 사용.



#include <windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
LPWSTR lpszClass=L"ApiBase";
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst=hInstance;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=(WNDPROC)WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=NULL;
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
while(GetMessage(&Message,0,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static HANDLE hFile;
DWORD dwWritten;
WORD wd=0xFEFF;
TCHAR strWrite[]=L" 이제 꿈나라로 떠납니다ㅎㅎ";
DWORD dwRead;
TCHAR strRead[MAX_PATH]; // 읽어들인 문자열을 저장할 버퍼.
switch(iMessage)
{
case WM_LBUTTONDOWN: // 마우스 왼쪽 클릭 시
hFile=CreateFile(L"FileInOutExx.txt",GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,0,NULL);
// 파일을 생성한다. 그 파일은 디버깅파일이 있는 디렉토리의 만들어지며, 이름은 FileInputExx.txt이다. 이것은 쓰기만 가능하며, 공유는 안 된다.
// 또한 상속은 하지 않으며, 파일이 없다면 만들어서 기록하며 있다면 내용을 덮어씌운다.
memcpy(strWrite, &wd,2);
// 유니코드 인식을 위하여 strWrite에 있는 2byte를 &wd(0xFEFF)에 저장.
WriteFile(hFile, strWrite, (wcslen(strWrite)+1)*sizeof(TCHAR), &dwWritten, NULL);
// 파일의 핸들값을 가지고오며, 두번째에는 입력할 문자열, 그 다음은 입력할 문자열의 크기, 실제로 쓰여진 바이트 수를 리턴하는 DWORD 변수의 포인터,
// 마지막은 비동기식 입출력이므로 NULL을 입력.
//CloseHandle(hFile); // 파일 사용이 끝나면, 사용된 핸들을 종료시키기.
return 0;
case WM_RBUTTONDOWN: // 마우스 오른쪽 클릭 시
hdc=GetDC(hWnd);
hFile=CreateFile(L"FileInOutExx.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
// FileInOutExx.txt라는 파일을 읽기모드로 생성하겠다는 의미. 또한, 세 번째 인수가 0이므로 파일은 공유하지 않으며, 이미 생성된 파일을 읽어오는 것이기 때문에 OPEN_EXISTING를 씀.
ReadFile(hFile,strRead,wcslen(strRead),&dwRead,NULL);
// 읽어올 파일의 핸들을 의미하며, 읽어온 데이터를 strRead 버퍼에 저장하고, 쓰려는 바이트 수 , 실제로 입력한 바이트 수 반환, 비동기식 입력 사용 x 하겠다는 의미.
TextOut(hdc,100,100,strRead,wcslen(strRead));
//CloseHandle(hFile); // 사용한 핸들 닫아주기.
ReleaseDC(hWnd,hdc);
return 0;
case WM_DESTROY:
if(hFile)
CloseHandle(hFile);
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage, wParam, lParam));
}


// 빨간색 글씨를
0 -> FILE_SHARE_READ로 변경하면 파일공유 가능






// 변경 전



// 변경 후





+ Recent posts