Sqlite3 소스코드에 있는 내용입니다.


윈도우 모바일 프로그래밍을 시작하는 대부분의 사람은 어디에서부터 어떻게 시작해야 하는지 막막할 것입니다.

요즘 모바일 프로그램을 해야할 사정이 생겨서 시작하게 되었는데 혼자알기에는 아깝고, 까먹을지 몰라서 간단하게 요약하고자 합니다.

Windows Mobile 프로그래밍의 시작은 어떻게 하는것이 좋을까요??

인터넷을 뒤져보면 아주 좋은 자료들이 많습니다.

어떤 기능을 하는 코드, 어떤 에러를 잡는 방법, 어떤 프로그램에 필요한 기술 등등 각종 단편적인 수많은 자료들이 존재하기 때문에 인터넷 자료를 기반으로 시작하시는 분들이 많습니다.

이런 방법도 매우 좋은 방법이긴 합니다. 하지만 프로그램을 배우는 흐름이 뒤죽박죽으로 섞이고 인터넷의 정보가 정확한 정보가 아닐 수도 있기 때문에 예상하지 못한 많은 시행착오를 겪을 수 있습니다.

그래서 저는 다음 방법을 추천합니다.

지금 곧장 가까운 서점에 가서 마음에 드는 책을 한권 사서 처음부터 차근 차근읽으십시오.

책의 서문과 Windows Mobile 시스템에 대한 이해, 그리고 계보 등을 이해하고 체계적으로 시작하는것을 추천합니다.

다만 이 글은 Windows Mobile 프로그래밍을 예전에 해봤다가 깜빡 기억이 안나는 분들을 위해서 준비했습니다.

다음 구성으로 연재를 할 예정입니다.

Windows Mobile 빌드환경 구성하기.

Windows Mobile 첫번째 프로그램 시작하기

Windows Mobile 더버깅 하기.

Windows Mobile 인터넷 연결하기.

Windows Mobile 리소스 파일 적용하기

Windows Mobile Sqlite를 활용한 DataBase 시스템

팀에서 따로 하는 프로젝트에 doxygen 을 활용합니다.

doxygen 에 대한 설명은 여러 사이트에서 잘 설명을 해놓았습니다. 되도록이면 여기가 아닌 잘 정리된 사이트를 참고하시기 바랍니다.

이 글은 단순히 제가 참고하기 위해서 작성한 글입니다.

Doxygen 예제

// <---- 프로젝트 전체 설명
/// @mainpage 프로세스가 종료되는 시점 후킹
/// @section intro 소개
/// - 소개    : 목표로 하는 프로세스에 해당 dll 을 injection 시킨다.
/// @section Program 프로그램명
/// - 프로그램명 : ExitProcessHook
/// - 프로그램내용 : 프로세스가 종료되는 시점을 dll 에서 알아내기 위해 후킹한다.
/// @section CREATEINFO 작성정보
/// - 작성자  : Ggil
/// - 작성일  : 2009-05-19
/// @section MODIFYINFO 수정정보
/// - 수정일/수정자 : 수정내역
/// - 2009-05-20/Ggil : ExitProcess 대신 ExitProcess 를 후킹함.

// 특정 파일에 대한 설명.
/// @file TerminateProcess.cpp
/// @brief DLL 메인 소스파일. TerminateProcess 후킹하려고 이름을 정했다가 후킹함수만 변경하고 이름은 그대로 둠.

#include "stdafx.h"

 

/// @brief Dll의 진입 함수.
///
/// @param hModule 현재 dll 의 모듈 베이스
/// @param ul_reason_for_call 진입 함수의 호출 타입? 이유? 호출시점?
/// @param lpReserved 말 그대로 예약된 파라미터
/// @return 처리 결과(TRUE : 성공, FALSE : 실패)

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 static PFN_TERM NewExitProcess_Target = NULL; // ExitProcess 함수의 포인터
 HMODULE hTargetModule = NULL;

 switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:

  break;
 case DLL_PROCESS_DETACH:

  break;
 }

    return TRUE;
}


다른 스레드에서 생성한 다이얼로그를 강제로 죽이려면??

pDlg->DestroyWindow() <== ?

이러면 제대로 종료되지 않습니다.

pDlg->CloseWindow() <== ?

마찬가지로 종료되지 않습니다.

SendMessage(pDlg->GetSafeHwnd(), WM_CLOSE, NULL, NULL)

종료되지 않습니다.


모달 다이얼로그를 종료시키는 방법은 EndDialog() 함수를 호출하는 방법뿐입니다.

pDlg->EndDialog(IDOK); 혹은  pDlg->EndDialog(IDCALCEL);

을 호출하면 해당 다이얼로그는 종료가됩니다.

삽질하지말자!!!

처음 시나리오.
1. LBUTTONDOWN 메세지를 받아서 최초 클릭위치 저장
2. MOUSEMOVE 메세지를 받아서 드래그 상태이면 이동한 만큼 다이얼로그 이동. 클릭위치 업데이트

이렇게 했었는데.. 뭐 가능할지도..안해봐서 모르겠지만 더 편한 방법이 있습니다.

바로 LBUTTONDOWN 메세지를 받으면 다이얼로그박스타이틀바 에 메세지를 보내는거죠.

즉 타이틀바를 클릭해서 드래그하는것 과 같은 효과를 주는겁니다.

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 RECT rect;
 GetWindowRect(&rect);
 if( ( point.x < rect.right  || point.x > rect.left ) ||
  ( point.y < rect.top || point.y > rect.bottom ) )
 {
  DefWindowProc(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
 }

 CDialog::OnLButtonDown(nFlags, point);
}

이러면 끝!!!

dll 이 자신이 로딩중인 프로세스의 죽는 시점을 알아내기 위해서 다음 함수를 후킹하면 됩니다.

// Ends the calling process and all its threads.
VOID WINAPI ExitProcess(
  __in  UINT uExitCode
);


어설프게 TerminateProcess 를 후킹해서 왜 안불려질까 멍청하게 고민을 하다니. ㅡㅡ;

다른프로세스에서는? 안해봤지만 후킹하지않고 ToolHelp API 으로 열심히 프로세스를 뒤지다가 없어지면 종료된 시점으로 간주하면 되지 않을까???
그냥 binary editor 으로 뒤져도 되지만 windbg 로 볼 경우 좀더 편하다.

준비물 : 분석할 exe 파일과 그 파일의 pdb

1. F6(File->Attach to a Process..) 으로 분석할 프로세스(exe) 선택.

2. 커맨드 창이 뜨면 .symfix+ c:\symbols 실행

3. File -> Symbol File Path 실행한 후 Browse.. 버튼을 클릭하여 pdb 파일이 있는 폴더를 선택.

4. 프로세스를 계속 실행시킬 경우 F5 키 누르고 멈출려면 Ctrl+Break 키 누름

5. .reload *  과 ld * 으로 심볼 다시 로딩
"ERROR : Symbol file could not be found."  에러는 다른 모듈(exe 가 로딩하는 각종 dll 등)의 심볼을 못찾으므로 발생하는 에러임. .무시

6. 마지막으로 lml 으로 제대로 로딩되었는지 확인... 실행파일의 심볼이 로딩되어 있어야함. 일반적으로 0x400000 위치.

여기까지 pdb를 로딩하는 방법.

이제 이걸 통해서 실제 심볼을 표시해보자.

x 실행파일이름!*검색할심볼명*
ex : x sample!*g_*     <== sample.exe 에서 g_ 가 들어가 있는 모든 심볼 표시
dt 실행파일이름!*검색할심볼명*
ex : dt sample!*g_*     <== sample.exe 에서 g_ 가 들어가 있는 모든 타입 심볼 표시

이러면 심볼이 주루룩 나타난다.

만일 pdb 파일이 실행파일과 싱크(?) 가 맞지 않을 경우에는 강제로 pdb 파일을 로딩해야한다.

.reload /i 실행파일.exe

그리고 다시 lml 으로 제대로 심볼을 로딩했는지 확인하면 끝!!!

마지막으로 팁으로...

심볼 이름으로 브레이크포인트 걸기 : bp 실행파일!심볼이름
특정 심볼(변수)의 정보 보기 : dt 실행파일!심볼이름
특정 심볼에 접근(쓰기)하는 경우 브포 걸기 : ? 실행파일!심볼이름   으로 주소를 찾고   ba w4 주소  를 입력함.
실행되고있는 스레드 정보 보기 : Alt + 9
해당 스레드의 콜스택 : 스래드 선택하고 kb
특정 명령어의 정보보기 : .hh 명령어

이상 끝!


CreateDirectory() 는 마지막 폴더만 생성하는 함수입니다.

다음은 원하는 Full Path 의 폴더를 생성시켜주는 함수입니다.

BOOL AutoCreateDirectory(TCHAR* dir)
{
 TCHAR path[MAX_PATH] = {0, };
 TCHAR *p = dir;
 int nStep = 0;
 BOOL bRet = FALSE;

 //   0    1    2    3
 // c:\test\1234\5678\23412
 while( true )
 {
  if (*p == '\\' || *p == NULL)
  {
   if (nStep >= 1)
   {
    _tcsncpy(path, dir, (p-dir));
    path[(p-dir)] = '\0';

    bRet = CreateDirectory(path, NULL);

    if (bRet == NULL && GetLastError() != ERROR_ALREADY_EXISTS)
    {
     TRACE("심각한 오류 : 폴더 생성 실패. 원인 %ld \n", GetLastError());
     return FALSE;
    }
   }

   if (*p == NULL)
    break;

   nStep++;
  }

  p++;
 }

 return TRUE;
}

휴~ 이넘의 지저분한 소스... 매번 느끼는거지만 초간단 플밍만 하니 소스가 이모양이지....

스피드핵은 기본적으로 타이머와 관련된 함수를 후킹해서 사용합니다.
GetTickCount(), timeGetTime(), QueryPerformanceCounter()

만일 윈도우에서 제공해주는 타이머 함수를 직접 구현한다면???

자료를 뒤져보니 Assemply 로 CPU 시간을 알아내는 코드가 있더군요.
출처 : http://abipictures.tistory.com/353

unsigned __int64 ddwCount;

_asm
{
RDTSC
mov DWORD PTR ddwCount, eax
mov DWORD PTR ddwCount+ 4, edx
}

RDTSC(Ream Time Stamp Counter) 은 8x86 CPU에서 CPU의 클럭값을 eax와 edx에 return하는 어셈입니다.


그런데 실제 돌려보니 CPU 클럭값이 초당 몇번 동작하는지 모르니 적용할려면 좀 노력을 해야할것같네요.

 int _tmain(int argc, _TCHAR* argv[])
{
 struct {
  DWORD dwTime1;
  DWORD dwTime2;
 } asmTimer, tmpTimer;

 for(int i=0; i<20; i++)
 {
  __asm
  {
   RDTSC
   mov DWORD PTR asmTimer, eax
   mov DWORD PTR asmTimer+4, edx
  }

  if (i>0)
  {
   printf("[%u]\t%lu\t[%lu]\t%lu\t[%lu]\n",
    i,
    asmTimer.dwTime1,
    asmTimer.dwTime1 - tmpTimer.dwTime1,
    asmTimer.dwTime2,
    asmTimer.dwTime2 - tmpTimer.dwTime2);
  }

  memcpy(&tmpTimer, &asmTimer, sizeof(asmTimer));

  Sleep(500);
 }
 
 return 0;
}

 [1]     4231356696      [139997214]     169     [0]
[2]     41459963        [105070563]     170     [1]
[3]     90353894        [48893931]      170     [0]
[4]     237211070       [146857176]     170     [0]
[5]     288734747       [51523677]      170     [0]
[6]     361892201       [73157454]      170     [0]
[7]     543081920       [181189719]     170     [0]
[8]     613704488       [70622568]      170     [0]
[9]     675258215       [61553727]      170     [0]
[10]    869067653       [193809438]     170     [0]
[11]    923720396       [54652743]      170     [0]
[12]    987591011       [63870615]      170     [0]
[13]    1064402699      [76811688]      170     [0]
[14]    1121647946      [57245247]      170     [0]
[15]    1170933692      [49285746]      170     [0]
[16]    1233143213      [62209521]      170     [0]
[17]    1304132819      [70989606]      170     [0]
[18]    1383210554      [79077735]      170     [0]
[19]    1434673859      [51463305]      170     [0]




 

VC 6.0 에서는 잘 컴팔 되던것이..

1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(207) : error C2146: syntax error : missing ';' before identifier 'dbch_size'
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(207) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(207) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(208) : error C2146: syntax error : missing ';' before identifier 'dbch_devicetype'
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(208) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(208) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(209) : error C2146: syntax error : missing ';' before identifier 'dbch_reserved'
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(209) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(209) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\dbt.h(213) : error C2143: syntax error : missing ';' before '*'

간단한 해결방법은

/wd 4430

컴파일 옵션을 추가하면 해결.

그런데 헤더파일 잴 위에

#include <windows.h>

를 추가해도 해결되는군.. 왜 그런지는 모름.

드라이버 첨부터 공부하는사람들...

드라이버 고수들이 누구나 추천하는 그책

"WINDOWS DRIVER MODEL"

본인도 이 책으로 드라이버에 입문(?) 을 했다.

그리고 일주일만에 포기했다. -_-;

이 책은 드라이버 입문자에게는 포기를 하게끔 만드는 강력한 마력이 있다.

왜냐하면!!!!!

처음 그걸 보면.. 이해가 안된다. 이해를 할 수 없다.

깡으로 반권을 읽었지만 결국 포기하고 말았다.

하지만 고수들이 추천했다면 당연히 좋은책임은 분명하다. 단지 입문자!!! 에게는 비추라는게 헤딩을 해본 본인의 생각이다.

그럼 나는 뭐 이 입문자를 벗어나서 드라이버를 자유자제로 제작하느냐??? 당연히 아니다.

오늘 첨으로 빌드해봤다. -_-;

그리고 앞으로 계속 연구를 해 볼것이다.

단지 입문자가 드라이버의 세계에 접근하기 편한 좋은 강좌를 모아서 링크를 올려놓고 이걸 통해서 나처럼 좌절하지 않기를 바라는 마음이다.

그 입문서를 모두 읽어 본 후에 비로소 WINDOWS DRIVER MODEL 을 읽는다면 아마도 이 책이 좋다~ 라고 생각할 것이다. (물론 본인의 생각은 아니다. 고수(?)의 의견을 빌리자면 그렇단 얘기다.)

아래 링크는 쉽게 드라이버의 세계에 입문하기 위해서 많은 도움을 주는 아주 좋은 조언자이니 꼭 읽어보길 바란다.


[초보자를 위한 Kernel based windows rootkit -1부]
http://beist.org/research/public/beginnerwinrootkit/beginnerwinrootkit.pdf
 - beist 랩에서 발견한 기초룻킷 강좌. 여기에 간단하게 드라이버 제작에 대한 설명이 포함되어 있다. 지금 읽으면서 처음 드라이버를 빌드할 수 있도록 가이드라인을 제시해주고 있다.


[드라이버 쪼물딱 거리기 1~3탄]
http://somma.egloos.com/2710282  <== 1탄
http://somma.egloos.com/2710303  <== 2탄
http://somma.egloos.com/2731001  <== 3탄
 - 유명한 쏘마님의 드라이버 입문 강좌이다.

[비주얼스튜디오에서 DDK Build를...]
http://hongyver.pe.kr/ttblog/705 
  - 커맨드라인을 벗어난 빌드환경을 구성하는데 많은 도움이 된다고 한다. 물론 해볼 예정.

[MS 사이트에서 찾은 기초자료]
http://download.microsoft.com/download/5/D/6/5D6EAF2B-7DDF-476B-93DC-7CF0072878E6/DrvDev_Intro.doc
  - 드라이버 빌드에 대한 기본적인 설명 문서

하나더 있는데 "은조님의 드라이버강좌" 홍선이 보내주기로 했으니 보내주면 링크 ㄲ (누가 김은조님이라고 했더라?)




한번씩 정말 기본적인것에 에러가 나서 시간을 허비하는 경우가 종종 있다.

오늘도 간단한 SendInput 함수를 이용한 예제를 만드는데 컴파일 에러가 나서 몇십분을 삽질한 경우인데 아무래도 다음번에도 똑같은 실수를 할까봐 미리 정리해본다.

디버깅을 하기 위한 방법에는 여러가지가 있지만

이 방법은 정공법으로써 pdb 와시스템이 남기는 디버깅 정보를 활용하는 방법이다.

참고로 나는 drwtsn32 를 띄우지 않고 ollydbg 를 레지스트리에 등록해놓고 디버깅을 하지만..

1탄.




2탄.



3탄..


홈페이지를 운영할때 마다 꼭 포함되어있던 내용인데...

한동안 MFC 를 안했더니 블로그에 없군..

 //파일 대화상자 생성
 CFileDialog pDlg(TRUE,NULL,_T("*.*"), OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, _T("모든 파일 (*.*)|*.*|"));
 //대화상자 실행
 if(pDlg.DoModal()==IDOK)
 {
  m_szFilePath.Format(_T("%s"),pDlg.GetPathName());
  UpdateData(FALSE);
 }


BROWSEINFO bi;
ZeroMemory(&bi, sizeof(BROWSEINFO));
bi.hwndOwner = m_hWnd;
bi.ulFlags   = BIF_RETURNONLYFSDIRS;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
BOOL bRet = FALSE;
TCHAR szFolder[MAX_PATH*2];
szFolder[0] = _T('\0');

if (pidl)
{

        if (SHGetPathFromIDList(pidl, szFolder))

        {

            bRet = TRUE;

        }

        IMalloc *pMalloc = NULL; 

        if (SUCCEEDED(SHGetMalloc(&pMalloc)) && pMalloc) 

        {  

            pMalloc->Free(pidl);  

            pMalloc->Release(); 

        }

    }

GetDlgItem(IDC_EDT_D_PATH)->SetWindowText(szFolder);

오늘 업체에서 메일이 왔다.

클라모듈에는 LPCSTR 인데 왜 서버모듈에는 LPCTSTR 이냐고.

설명이 필요없다.

제목그대로 그걸 정리해놓은 표니까 참고

최근들어서 골머리를 썩게 하는 이넘의 벽핵(WallHack).

사실 벽핵이라면 여러가지 핵을 통틀어서 말하는데

1. 화면상의 유닛의 이동범위를 제한(벽을 만듬)함으로써 유닛을 한쪽으로 쏠리거나 모으는 경우
2. 게임화면상의 벽을 통과시키거나 건너편을 볼수 있는 경우
3. 그다음은 생각나지 않음. -_-;;

이중에 Wallhack 의 2번째에 대해서 자료를 찾아보았다. ( 이제부터 열심히 공부를.. )

순전히 다른 사이트의 내용을 뱃겨옴. ㅡㅡ;

[간단한 WallHack제작]


 [WallHack에 대한 링크1]
http://forum.gamedeception.net/showthread.php?t=8084

현재 피시의 작업그룹과 도메인을 알아내는 방법을 알아보자.

스왑!

"물건과 물건을 바꾸다" 라는 뜻이다.

프로그램에서는 변수1 과 변수2 의 값을 바꾼다는 의미로 받아들일 수 있다.

이 스왑에 대한 간단한 팁.

OS 버전을 알아 내는 방식 참.. 지랄같이 만들어 두었습니다.

뭐 MS 의 정책상 어쩔수 없는것이겠지만 사용하는 우리 입장에서는 좀더 깔끔하게 보내준다면 좋을텐데요..

아무튼 OS 에 대한 버전을 알아 낼려면 다음과 같이...

프로그래밍을 하다 보면
"내코드가 에러가 나긴 났는데 어느위치까지 났을까?"
라는 의문에 다음과 같은 로그를 남기는 경우가 많다.
....
printf("step1");
....
printf("step2");
....

하지만 이렇게 하는것보다 좀더 효율적인 매크로 __LINE__ 과 __FILE__ 에 대해서 알아보자.

OS 라면 사실 구체적으로 M$ 윈도우 시스템입니다. 이 방법이 리눅스나 유닉스에 동작할리 없습니다.

다음은 데브피아에서 긁어온 내용입니다.

매번 스레드를 사용할려고 인터넷 뒤지는거 귀찮다.

예전에 홈페이지에 만들어두었던 스레드 예제가 지금은 너무 아쉽네

그래서 여기에 다시 하나 만들어서.. 활용하자!!!!

하나의 프로그램안에서도 여러 스레드를 사용하는데 하물며 하나의 제품에 여러 프로세서가 존재할 수 있습니다. 이 프로세서들은 서로 긴밀한 관계로 동작하는 경우가 많은데 이때 사용하는 프로세서간의 통신 방법중 이벤트에 대해서 정리해봅니다.

관리자 프로세서가 쫄다구 프로세서를 종료시키기.


 

" 출처 : 데브피아에서 vc 사용할 때 유용한 매크로가 있어서 퍼왔습니다. "

라고하는데 저도 그 카페에서 퍼왔습니다. -_-;

출처의 출처 : http://blog.naver.com/unbraid?Redirect=Log&logNo=29293013

비주얼 툴 재미있게 사용하기.
■ 편집 단축키


■ 디버그 단축키

■ 주석 매크로..

잘 활용 하시길...

마소(Micro Software 잡지)를 읽다가 발견한팁.

상수형태의 배열의 갯수를 알아내자.

+ Recent posts