Admin | Write | GuestBook
[공지] 해당 블로그에 용건이 있으신 분께서는 http://blog.fore.kr/ 의 방명록(Guestbook)으로 부탁드립니다.
심심해서 풀어본 키젠미
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2013. 4. 6. 08:54 ) | 신고

 

 

간만에 키젠미 해보고 싶어서 했다가 풀소스 작성해버림.

 

[ 키젠미 파일 ]

KGM1-qwertydid.rar

관련 링크 : http://tuts4you.com/download.php?view.2127

 

[ 소스 ]  

KeygunMe1.c

 

순수 어셈으로 작성된 듯한 코드들과

 

거기다 패킹되어있지도 않고, 안티디버깅도 어려운거 쓰지 않았고 . . .

 

난이도가 3/10 인데, 딱 이정도인듯 싶다.

 

추가로, 코드 후킹만 좀 하면 키젠따윈 순식간에 만들법하다.

 

소스는 C언어로 작성함.

 

내가 작성해두고 외계어 적어둔거 같네.

 

해설 적고 싶은데 너무 양이 많아서 때려침.

(어차피 볼사람도 없을거고 . . .)

 

혹시나 소스보고 궁금한거 있으면 덧글로 ㄱㄱ

 

 

심심해서 적어보는 C언어 간략한(?) 총정리.
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2013. 3. 21. 05:58 ) | 신고

 

 

필수적이라 생각하는 부분만 간략하게 요약해서 적음.

 

※ main 함수.

 

기본 형태> http://msdn.microsoft.com/en-us/library/6wd819wh.aspx

#include <stdio.h>

int main(int argc, char *argv[], char *envp[]){

   return 0;

}

원래 기본 형태는 이런데, 아래와 같이 간추려서 쓰는 경우가 대부분이다.

 

Visual Studio 사용자 >

#include <stdio.h>

void main(){

}

※ 6.0 이하의 사용자는 main() 만 선언해도 인식된다.

 

Dev C++ 사용자 >

#include <stdio.h>

int main(){

   return 0;
}

 

Tip > 아오 . . . 컴파일러 하고 실행하면 그냥 꺼져요.

 

해결법 01. >

#include <stdio.h>

#include <conio.h>

void main(){

   코드 작성 후

   getch();

}

 

해결법 02. >

#include <stdio.h>

#include <stdlib.h>

void main(){

   코드 작성 후

   system("pause");

}

 

컴파일러 옵션으로 설정하면 위와 같이 코드 작성할 필요 없는데

 

컴파일러마다 달라서 패스함.

 

 

※ 타입

 

int - 정수형 4bytes

char - 문자형 1bytes

float - 실수형 4bytes

 

그 외에 조금 이야기하면 long(4bytes), short(2bytes), double(8~16 os에마다 다름) 등이 있는데

 

컴퓨터 전공이 아닌 이상 거의 배우지도 않는다 생각함.

 

참고로, 영문, 숫자 글자같은 경우엔 1bytes(char)로 충분하지만, 한글 같은 경우엔 2bytes을 소요하므로

 

short 으로 선언하거나 char을 배열로 2개이상 선언해야한다.

 

 

※ 함수

 

일반 형태 >

[리턴형태] [함수 이름](인자...){

   소스...

   return (리턴형태의 값);

}

 

예제 >

int add(int a,int b){

   return a+b;

}

printf("%d",add(1,2));

결과 : 3

 

번외 01. > printf 의 예약된 문자

%d : 음수 표현가능한 정사

%f : 실수

%lf : 32bit 실수

%x : 16 진수

%o : 8 진수

%s : 문자열

%c : 문자

이스케이프 문자 >

'\n' : 개행

'\r' : 리턴행

'\t' : 탭

 

※ 배열

 

저놈의 타입놈들을 따로 선언하는게 아닌 뭉텅이로 선언시킴.

 

int i[10]; // int 형 변수가 10개가 뭉쳐있음.

 

표현 방식 > printf("%d",i[0]); // i 배열의 첫번째 숫자를 출력함.

 

 

번외 02. > scanf 함수 간단한 사용법

int a;

char b[10];

scanf("%d",&a); // a 변수에 사용자가 입력하는 정수형 수를 받아옴.

scanf("%s",b); // b 배열에 사용자가 입력하는 문자열을 받아옴.

 

 

※ 연산자

 

[ 단순 ] 사용되는 사례 : 그냥 이건 가지가지 나옴.

◎ + : 더한다.

◎ - : 뺀다.

◎ / : 나눈다.

◎ * : 곱한다

◎ % : 나머지 값.

나머지 값만 예>

int a = 100%2;

printf("%d",a);

결과 : 0

100을 2로 나누면 나머지가 0이므로 0

 

 

[ 증감 ] 사용되는 사례 : 이거도 가지가지 나옴.

++ : 1씩 증가시킴.(포인터의 경우 해당 타입의 바이트만큼 주소값을 옮김)

-- : 1씩 감소시킴.(포인터의 경우 해당 타입의 바이트만큼 주소값을 옮김)

예 01>

int a = 1;

printf("%d",a++);

printf("%d",a);

결과 > 1, 2

예 02>

int a = 1;

printf("%d",--a);

printf("%d",a);

결과 > 0, 0

 

[비트] 사용되는 사례 : 다중 선택이 필요한 경우, 압축, 암호화 기술 등에 사용.

◎ [값]<<[옮길 크기] : 해당 값의 비트를 왼쪽으로 옮길 크기만큼 옮긴다.

◎ [값]>>[옮길 크기] : 해당 값의 비트를 오른쪽으로 옮길 크기만큼 옮긴다.

예 >

1<<2 : 결과 : 5

1>>2 : 결과 : 0 

 

◎ ~[A값] : A값의 비트를 1을 0으로 0을 1로 바꾼다.

예 >

int a = 5; // (100)

a = ~a; // (100) = (011)

printf("%d",a);

결과 : 3 (011)

5(100) 를 1을 0으로 0을 1로 바꾸면 3(011)

 

◎ [A값]^[B값] : A값과 B값을 비교해서 서로 비트가 다르면 1 같으면 0으로 바뀐다.

예 >

int a = 1;//(01)

int b = 2;//(10)

printf("%d",a^b);

결과 > 3(11)

1(01) 와 2(10) 비교해서 첫번째 비트를 비교해서

0 과 1이니까 1로 두번째비트를 비교해서

1과 0이니 1이 되서 3(11)이 된다.

01

10

11

이런 느낌.

 

◎ [A값]|[B값] : A값과 B값을 비교해서 둘다 비트가 0이 아니면 무조건 1이다.

int a = 5;//(100)

int b = 1;//(001)

printf("%d",a|b);

결과 > 6(101)

 

◎ [A값]&[B값] : A값과 B값을 비교해서 둘다 비트가 1이 아니면 무조건 0이다.

int a = 7; // (110)

int b = 3; // (011)

printf("%d",a&b);

결과 > 2(010)

 

[논리]

[A값] == [B값] : A값과 B값이 같으면 참, 아니면 거짓.

[A값] != [B값] : A값과 B값이 같지 않으면 참, 아니면 거짓.

[A값] <= [B값] : A값이 B값보다 작거나 같으면 참, 아니면 거짓.

[A값] >= [B값] : A값이 B값보다 크거나 같으면 참, 아니면 거짓.

[A값] < [B값] : A값이 B값보다 작으면 참, 아니면 거짓.

[A값] > [B값] : A값이 B값보다 크면 참, 아니면 거짓.

![A값] : A값이 참이면 거짓, A값이 거짓이면 참

 

[간략형]

◎ +=, -=, /=, *=, >>=, <<=, &=, ~=, ^=, |=

하나만 예>

int a = 0;

a += 1; // a = a + 1 와 동일함.

printf("%d",a); 

 

 

※ 예약어(명령어) - 조건문

 

# if 조건문

if(조건문)

else if (조건문)

else

예제 01> if문 일반적인 사용

int a = 1, b = 2;

if ( a == 1 )

  printf("a = 1\n");

if ( b == 1 )

  printf("b = 1\n");

else if ( b == 2 )

  printf("b = 2\n");

if ( a == 2 )

  printf("a = 2\n");

else

  printf("none\n");

결과 >

   a = 1

   b = 2

   none

 

예제 02> 재귀 함수를 이용한 if문 사용

int factorial(int a,bool bInit){

   static int nRetnNum = 0;

   if ( bInit == true )

      nRetnNum = 0;

   if ( a != 0 )

      factorial(a-1,false);

   return RetnNum;

}

printf("%d",factorial(10,true));

결과 : 55

static 로 선언된 변수는 프로그램이 끝나기 전까지 없어지지 않는다.

 

 

# switch 조건문

switch(정수형 혹은 정수를 표현 가능한 변수){

   case (조건 정수 혹은 정수를 표현 가능한 기호):

   break;

   default:

   break;

}

예제 >

int a = 'a';

switch(a){

   case 1:

   break;

 

   case 'a':

   case 'b':

      printf("a");

   break;

 

   default: // 위 조건에 하나도 맞지 않는 경우 이쪽에 들어옴.

   break;

}

결과 : a

 

# ?: 조건문

(조건문)?참일경우:거짓인경우;

예>

int a = 1;

int b;

b = (a == 1)?2:3;

printf("%d",b);

결과 : 2

 

#goto 문

int main(){

   goto MY_GOTO;

   printf("a");

MY_GOTO:

   printf("b");

   return 0;

}

결과 : b

 

 

※ 예약어(명령어) - 반복문

 

# for 반복문

기본문 : for(초기화문;조건문;연산식);

예제 01>

int i;

for(i=0;i<5;i++)

printf("%d ",i);

결과 01> 0 1 2 3 4

Tip : for 다음으로 넘어가는 함수 혹은 연산식이 1줄밖에 없을 경우 { } 생략 가능.

예제 02> if 문을 활용한 continue, break 사용법

int i;

for(i=0;i<5;i++){

   if ( i == 1 )

      continue;

   if ( i == 3 )

      break;

   printf("%d ",i);

}

결과 02> 0 2

continue 의 경우엔 반복문 + 조건문 상태에서만 가능하며, 해당 조건에 맞을시

반복문 continue 밑으로 진행되는 코드가 전부 무시되고 다음 반복문으로 넘어간다.

break 의 경우엔 반복문 + if 문에 맞을 경우, 반복문에서 빠져 나오게 되고,

switch 의 경우엔 switch 문에서만 나오게 된다.

 

# while 반복문

기본문 : while(조건문);

예제 >

int i = 5;

while(i)

printf("%d ",i--);

결과 > 5 4 3 2 1

Tip : 0은 모든 조건의 거짓이 된다. ( 반대로 0 초과하는 모든 수는 참 )

따라서, while 루프 돌 때 0이면 자동적으로 탈출하게 된다.

 

# do..while 반복문

기본문 : do{~}while(조건문);

예제 >

int i = 5;

do

printf("%d ",i--);

while(i);

결과 > 5 4 3 2 1

 

※ 포인터

 

int i;

int *p = &i;

printf("%d %d %d",&p,p,*p);

결과 : &p = p라는 포인터 변수의 주소, p = i라는 변수 주소, *p = i의 값.

※ 포인터도 변수임을 명심.

 

대표적인 Swap을 예로함.

 

예 01. ( 포인터 변수를 이용한 swap )

void swap(int *a,int *b);

 

int i = 2;

int j = 1;

swap(&i,&j);

printf("%d %d",i,j);

 

void swap(int *a,int *b){

   int t = *a; // a 변수에 b 변수로 저장하면 a 값이 사라지므로 임시로 a의 값을 저장해둠.

   *a = *b; // a 변수에 b 변수 값으로 저장함.

   *b = t; // b 변수에 임시로 저장한 a값을 저장함.

}

 

예 02. ( 참조 변수를 이용한 swap )

void swap(int &a,int &b);

 

int i = 2;

int j = 1;

 

swap(i,j);

printf("%d %d",i,j);

 

void swap(int &a,int &b){

   int t = a; 

   a = b;

   b = t;

}

 

 

그 외에 포인터의 계산 등이 있는데, 아마 컴퓨터 관련 전공자 아니면 배우지 않으리라 생각함.

 

Tip > 안쓰려다 써보는 간략 포인터 계산.

int i[10];

int *p1 = &i[0], *p2 = &i[3];

printf("%d",p2-p1);

결과 : 3

당연히 3 이 나오겠냐 생각할지도 모르겠지만, 조금 생각이 있는 사람이면 12 를 생각했을 것이다.

(int 변수가 4bytes 를 가지고 있기 때문에)

하지만, 컴파일러가 컴파일할 때 자동적으로 4로 나눠버려서 기계어로 넣어버리기에 3이 맞다. 

 

※구조체

 

예 >

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct _STUD{

   char cName[20];

   int nNum;

   _STUD *NextStud;

};

// 위와 같이 변수 뿐만 아니라 함수도 집어 넣을 수 있다.

// 예를 들어

// struct _STUD{

//    int a;

//    int b;

//    void add(){

//       return a+b;

//    }

// };

// _STUD i;

// i.a = 1;

// i.b = 2;

// printf("%d",i.add());

// 위와 같은 식으로도 표현 가능하다.

 

int main(void){

   _STUD Stud01;

   _STUD *Stud02;

 

   // 동적 메모리 할당. malloc(할당 메모리 크기)

   // malloc 함수의 리턴형은 void의 포인터형(void *)이므로 캐스팅이 필요함.

   Stud02 = (_STUD *)malloc(sizeof(_STUD));

 

   // 문자열 복사 함수. strcpy(dest,source)

   // dest : 저장할 메모리 주소

   // source : 복사해올 메모리 주소

   // 일반적으로 선언된 구조체내의 변수를 불러올땐 "." 을 이용하고

   // 포인터로 선언된 구조체는 -> 으로 표현한다.

   strcpy(Stud01.cName,"FORE01");

   strcpy(Stud02->cName,"FORE02");

   // 위 strcpy(Stud02->cName,"FORE02"); 의 경우에

   // strcpy(Stud02[0].cName,"FORE02"); 으로도 표현이 가능하다. 

 

   Stud01.nNum = 1;

   Stud02->nNum = 2;

 

   printf("01 Name : %s\n",Stud01.cName);

   printf("01 Num : %d\n",Stud01.nNum);

   printf("02 Name : %s\n",Stud02->cName);

   printf("02 Num : %d\n",Stud02->nNum);

 

   Stud01.NextStud = Stud02;

 

   // 링크드 리스트를 위한 예제

   // Stud01.NextStud 에 Stud02 의 주소를 저장시켜 Stud01 을 통해 Stud02 를 불러온다.

   printf("Addtional Name : %s\n",Stud01.NextStud->cName);

   printf("Addtional Num : %d\n",Stud01.NextStud->nNum);

 

   // 메모리를 해제한다.

   free(Stud02);

 

   system("pause");

 

   return 0;

}

 

결과 >

01 Name : FORE01

01 Num : 1

02 Name : FORE02

02 Num : 2

Additional Name : FORE02

Addtional Num : 2

 

 

※공용체

 

예>

union _MY_SHARE{

   int a;

   int b;

   int c;

};

_MY_SHARE  i;

i.a = 1;

printf("%d %d %d",i.a,i.b,i.c);

 

결과 : 1 1 1

 

 

※ 전처리기, 매크로, enum

 

#define [이름] [값,식,타입,함수,매크로값 등등..]

 

예 >

#define MAX_NUM 10

#define ADD_DEF(a,b) (a+b)

 

printf("%d",ADD_DEF(MAX_NUM,5));

결과 : 15

 

#if (조건)

#elif (조건)

#else

#endif

 

예>

#define _MY_SOURCE

 

#if _MY_SOURCE

   printf("a");

#else

   printf("b");

#endif

 

결과 : a

 

 

typedef (변수 타입) (새로운 이름 명명)

 

예>

typedef int MyInt, *pMyInt;

 

int main(void){

   MyInt a = 1;

   pMyInt p = &a;

   printf("%d %d %d",&p, p, *p);

}

결과 : &p = p라는 포인터 변수의 주소, p = i라는 변수 주소, *p = i의 값.

 

enum (이름){ 정의값 }

 

예>

enum _stud{

   ST_FORE01 = 10,

   ST_FORE02,

   ST_FORE03

};

printf("%d %d %d",ST_FORE01,ST_FORE02,ST_FORE03);

결과 : 10 11 12

 

 

 

아마 이정도면 어느정도 문제 없지 않을까 ?

 

이거 적는데 솔직히 1시간이면 될 줄 알았는데 2시간 걸림 -_- ; ; ;

( 적으니까 이거도 적어야하고 이거 적고나니까 저거도 적어야겠고 . . . )

 

여기서 안담은게 좀 있는데, 예를 들어 ##, 비트형 혹은 비트 분할형 변수 선언, const,

 

'\' 의 사용법(다중 개행, 바이너리 표현 등), printf, scanf 의 상세한 사용법 등이 있는데

 

어차피 대학에서 배울거면 전공이 아닌 이상 안나올거 같음.

 

자세한건 관련 서적 찾아보면 될 거 같다.

 

 

 

FSCH BETA 1.0v User Manual
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2013. 3. 6. 21:04 ) | 신고

 

 

 

 

Fore's Secret Clipboard Hooker BETA 1.0v

 

[기본 인터페이스]

 

이리 생겨 먹었다.

 

우선, 제일 왼쪽 메뉴에 파일을 눌러보면

 

 

 

[ 파 일 ]

 

 

위와 같이 뜬다.

 

[창을 항상 위에]

- 딴창에 안가려지고 게속 항상 위에 있는다.

 

[텍스트 후커 설정]

- 텍스트 상세 옵션을 들어간다.

 

[텍스트 파일로 저장]

- 유니코드로 기록을 저장한다.

 

[프로그램 종료]

- 끈다.

 

 

[ 클 립 보 드 옵 션 ]

 

 

[ 클립보드 감시 ]

- 이거 켜야 적용된다.

 

[ 한글 감시하지 않음 ]

- 이거 켜두면 인터넷 웹서핑이나 요딴거 할 때, 클립보드에 한글 복사되서 보드에 뜨는걸 방지해준다.

 

[ 한줄씩 출력 ]

- 말그대로 한줄씩만 보여줌.

 

[ 클립후커 내용 지움 ]

- 여태까지 로그 싹다지워버림

 

[ 번역기 사용 ]

- 사용한다. 번역기를

 

[ 번역 출력 방식 ]

- 위 메뉴안에는 '원문+번역문' 출력 기능이 있는데, 체크해두면 원문과 번역문이 동시에 출력된다.

 

[ 배경색 설정 ] 

- 배경색 설정한다.

 

[ 글씨색 설정 ]

- 글씨색 설정한다.

 

[ 폰트 설정 ]

- 글씨 모양, 크기 꼴리는데로 바꿀 수 있다.

 

 

 

 

[ 파일 - 텍스트 후커 설정 ]

 

 

[ Hook Program - Path ]

- Agth, Ith 등 옆에 있는 Browse 버튼을 눌러 찾아주면 된다.

 

[ Hook Program - Type ]

- 설정해주면 도움된다.

 

[ Hook Program -Other program command line ]

- Aght, Ith 외에 다른 프로그램이 나오고 그 프로그램이 커멘드 라인으로 실행 가능하다면

Type 에서 Other Program 눌러주고 커멘드 라인 적어주면 된다.

커멘드 라인에 예약어가 두개 정도 있다.

$PROCESSNAME$ = 프로세스 이름이 적용된다.

$PROCESSID$ = 프로세스 ID가 적용된다.

 

Agth 커멘드라인을 예로 들면 Agth /L411 [/Hcode etc..] [/P(ProcessId)] 로 커멘드가 적용되는데

이때 Other Program 을 적용시키고 /L411 /HS-4@FFFFFF /P$PROCESSID$ 라 적어도

Agth 가 정상적으로 실행된다.

 

[ Hook Process ]

밑에 버튼에 Save & Attach 버튼을 이용할 때 써먹으면 유용할지도 모른다.

 

[ Hook program additional code - Additional code ]

Agth나 Ith 를 이용할 때, H 코드를 여기다 입력해주면 된다.

 

[ Startup ]

- Only Text window : 프로그램 실행시 텍스트 윈도우를 먼저 띄워준다.

- User Setting window : 프로그램 실행시 위 설정화면을 먼저 띄워준다.

- Text window & Hook program : 프로그램 실행시 텍스트 윈도우와 Hook Program 에

설정된 프로그램을 동시에 실행시켜준다.

※ Text window & Hook program 사용 시, 프로세스 Attach 는 되지 않으므로

ITH - Save 기능 이용할 때 유용함.

 

 

- 끝 -

 

p.s > 아참, 텍스트창에 옮겨진 모든 로그 클립보드 복사도 가능함.

 

 

위 프로그램 장점과 하자 : http://foreblog.tistory.com/631

 

BETA 1.0 v 계획에 따른 완성도 : 100 %

 

아마 배포 예정일자 : 3/9 [지인한정]

 

< 1.0v 향후 추가 업데이트 방향 >

- 한글 및 기타 문자열 감시하지 않음 or 스마트 감시(적당히보고 감시 안함)

- 프로그램 내 유저 번역 처리문 추가

- 플러그인 및 SDK 배포 예정

- 꼴리면 웹업데이트 기능도 추가함.

 

심심하니 fread, fwrite, fseek, ftell 구현. (Windows)
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2012. 10. 21. 19:10 ) | 신고

 

# fread

 

 size_t __cdecl fread( void *buffer, size_t size, size_t count, FILE *stream){
 unsigned long ul_rs = 0; //unsigned long return size
 ReadFile( (HANDLE)_get_osfhandle(stream->_file),
     buffer,
     count*size,
     &ul_rs,
     NULL) );
  return (size_t)ul_rs;
 }

 

 

# fwrite

 

 size_t __cdecl fwrite( void *buffer, size_t size, size_t count, FILE *stream){
 unsigned long ul_rs = 0; //unsigned long return size
 WriteFile( (HANDLE)_get_osfhandle(stream->_file),
    buffer,
    count*size,
    &ul_rs,
    NULL) );
 return (size_t)ul_rs;
 }

 

 

# fseek

 

 #define SEEK_SET FILE_BEGIN
 #define SEEK_CUR FILE_CURRENT
 #define SEEK_END FILE_END

 

 int __cdecl fseek( FILE *stream, long offset, int origin ){
  return (SetFilePointer(_get_osfhandle(stream->_file),offset,origin))0:(int)GetLastError();
 }

 

 

# ftell

 

 int __cdecl ftell(FILE *stream){
  return (int) SetFilePointer(_get_osfhandle(stream->_file),0,FILE_CURRENT);
 }

 

 

 

심심하니, 쓰레드에 대해 이야기해보자.
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2012. 10. 10. 14:52 ) | 신고

 

[번뜩 !]

 

진짜 할거없네 . . . 쓰레드에 대해 이야기해보자.

 

주제는 크게 지역변수와 쓰레드와의 관계이다.

 

쓰레드는 한 프로세스에 여러일을 동시에 해주는거처럼 보이게하는 아주 편리한 역활을 하고 있다.

 

이 편리한 쓰레드는 윈도우상 크게 쓰래드 함수가 2가지 종류로 존재한다.

 

 

 < CRT(C-RunTime) 함수 >

 

 uintptr_t _beginthread( 
   void( *start_address )( void * ),
   unsigned stack_size,
   void *arglist 
 );

 uintptr_t _beginthreadex( 
   void *security,
   unsigned stack_size,
   unsigned ( *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr
 );

 

 < 출처 >

 http://msdn.microsoft.com/en-us/library/kdzttdcb(v=VS.80).aspx

 

 

 

 < WIndows API 함수 >

 

 HANDLE WINAPI CreateThread(
  _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_       SIZE_T dwStackSize,
  _In_       LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_   LPVOID lpParameter,
  _In_       DWORD dwCreationFlags,
  _Out_opt_  LPDWORD lpThreadId
 );

 

 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
 );


 HANDLE CreateRemoteThreadEx(
  _In_       HANDLE hProcess,
  _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_       SIZE_T dwStackSize,
  _In_       LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_   LPVOID lpParameter,
  _In_       DWORD dwCreationFlags,
  _In_opt_   LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
  _Out_opt_  LPDWORD lpThreadId
 );
 ※ CreateRemoteThreadEx 의 경우 Windows 7 상위계열에서만 사용가능
 

 < 출처 >

 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx

 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx

 http://msdn.microsoft.com/en-us/library/windows/desktop/dd405484(v=vs.85).aspx

 

 

귀찮으니 사용 방법은 출처를 확인.

 

위 빨간색 부분을 제일 많이 애용한다.

 

그럼, 위 쓰레드는 어떤식으로 함수가 호출되는가 ?

 

[WIndows XP]

_beginthread -> CreateThread -> CreateRemoteThread

[Windows 7]

_beginthread -> CreateThread -> CreateRemoteThread -> CreateRemoteThreadEx

※ Windows 7 은 분석해보지 않아서 확실하지 않습니다.

 

이런식으로 호출된다.

 

결론적으로 윈도우에서는 CreateRemoteThread로 호출하는게 제일 빠른 결론이 나옴.

 

이야기가 산으로 갔는데, 쓰레드생성시 Parameter에 지역변수를 사용하면 안된다 ?

 

답은 'NO' 이다. 사용해도 되는데, 문제는 정적변수로 지역변수를 사용해야한다.

 

 

 잘못된 예

 

 #include <windows.h>

 #include <stdio.h>

 

 DWORD WINAPI CallThread(LPVOID pVal){

   DWORD dwCnt = 0;

 

    if ( pVal )

       while(dwCnt++<10){

          printf("%d\n",*(int *)pVal);

          Sleep(1000);

       }

    return 0;

 }

 

 HANDLE WINAPI Call(){

    DWORD dwThreadId;

    HANDLE hThread;

    int nVal = 1;

 

    hThread = CreateThread(NULL,0,CallThread,&nVal,0,&dwThreadId);

    if ( hThread )

       return hThread;

    return NULL;

 }

 

 int main(void){

    HANDLE hThread;

 

    hThread = Call();

    if ( hThread ){

       WaitForSingleObject(hThread,INFINITE);

       CloseHandle(hThread);

    }

 

    return 0;

 }

 

 

 

 올바른

 

 #include <windows.h>

 #include <stdio.h>

 

 DWORD WINAPI CallThread(LPVOID pVal){

   DWORD dwCnt = 0;

 

    if ( pVal )

       while(dwCnt++<10){

          printf("%d\n",*(int *)pVal);

          Sleep(1000);

       }

    return 0;

 }

 

 HANDLE WINAPI Call(){

    DWORD dwThreadId;

    HANDLE hThread;

    static int nVal = 1;

 

    hThread = CreateThread(NULL,0,CallThread,&nVal,0,&dwThreadId);

    if ( hThread )

       return hThread;

    return NULL;

 }

 

 int main(void){

    HANDLE hThread;

 

    hThread = Call();

    if ( hThread ){

       WaitForSingleObject(hThread,INFINITE);

       CloseHandle(hThread);

    }

    return 0;

 }

 

 

이런 느낌이다.

 

그럼 왜 지역 변수로 사용하면 안되는걸까 ?

 

정적 변수의 경우엔 '자신만의 저장소(메모리주소)를 독립적으로 가지고 있는' 반면

 

지역 변수의 경우엔 '함수 호출시에 변수를 할당' 하기 때문이다.

 

따라서, 해당 함수가 끝나면, 할당된 지역변수는 해제되고 해제된 지역변수 메모리 주소는

 

다른 함수등에 의해 새로운 값으로 덮어씌워지게 된다.

 

물론, 지역변수가 해제되고 해당 지역변수의 주소에 있는 메모리의 값이 변동이 없다면

 

값은 바뀌지 않는다.

(하지만, 그런일은 거의 없다.)

 

[ 잘못된 예의 예제 그림 ]

 

 

[ 올바른 예의 예제 그림 ]

 

그림으로 나타내면 이런 느낌 ?

 

Local Memory 부분에서 서로의 값이 충돌하는 사태가 벌어져서 지역변수로 쓰면 안된다는 이야기.

 

그럼 여기서 문제

 

 

 

이런것도 가능할까 ?

 

 

이야기는 여기서 마치도록 하겠습니다 ' ' ;

 

 

 

 

 

Category
분류 전체보기 (605)
Notice (6)
Programming (79)
Release Program (19)
Release Patch (14)
Programming Talk (46)
DISKER (1)
FSCH (7)
Caption (0)
Rest Time ! (443)
Hobby (64)
Tour (5)
Blind Post (0)
Recent Post
Recent Comment
Link
Calender
«   2024/12   »
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
Total :
Today :
Yesterday :