본문 바로가기
Programming/Tips(C++,C#)

0120

by 곰네Zip 2009. 1. 20.

* ::EnumProcesses(저장소,크기,저장갯수) : 시스템에서 현재 수행중인 프로세스들의 리스트를 가져온다.

 HANDLE hProcess  = ::OpenProcess(flag,false,pid);
  flag = PROCESS_QUERY_INFORMATION : 프로세스정보퍼미션얻기
          PROCESS_VM_READ : 가상메모리 읽기권한
 ::GetModuleFileNameex(HANDLE,NULL,buffer,Name) : 모듈이름 가져오기.
 =>커널에서 드라이버를 가지고 수행되는 것이 있다. 그것을 이용하자.

*메시지 후킹하기 - PE파일(실행파일임)을 찾아서 뒤져보자.
 -런타임시 가상메모리 주소 변경 -> 많이쓰인다.
 -IAT(Import Address Table)을 런타임시 변경
- 윈도우실행파일의 구조와 원리를 보자.

*프로세스 정보찾기 (2) - 스냅샷 API (옛날방법)
 HANDLE hSnapshot = CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
 PROCESSENTRY32 pe32 = { sizeof(pe32) };
loop을 돌면서 사용한다.

*IPC
 1) File을 이용하여 IPC를 한다.
 2) 레지스트리를 이용하여 IPC를 한다.
 3) DDE
 4) Shared Memory (자주쓰임) : End-User에서만 나오는 케이스임. 접근권한 설정을 고려해야함.
    만약 권한의 밸런스가 안맞다면 높은쪽에서 권한을 낮추어주면 된다. (그게 조금 더 쉽다)
 5) Socket (자주쓰임) : 네트워크를 이용한 케이스.

*레지스트리
 DB임. R/W가 잦다. 스스로 동기화를시킨다. 참조가 잦은거는 스스로 메모리에 올린다.

*API Hook을해서 실행차단가능
  1)메시지 후킹
  2)NT계열에서 CreateRemoteThread << 이걸 사용하자. 내가 지정해주는 함수를 사용하자.
 메모리 호출주소를 잘보자 : 게임가드 핵 가능하다.

*SharedMemory를 이용한 IPC시...
-헤더파일
 HANDLE  m_hMap;
 TCHAR*  m_pSharedMemory;
 CMutex  m_Mutex;
 CEvent  m_ExitEvent;
 CEvent  m_ReadEvent;

-소스코드
 -생성자
 constructor :m_Mutex(FALSE,TEXT("IPC_TEST_MUTEX")),  m_ExitEvent(FALSE,TRUE),
   m_ReadEvent(FALSE,TRUE,이벤트아이디1)){
    //initialize
 }

-쉐어드메모리 초기화함수
BOOL CSharedmemdemoApp::InitSharedMemory()
{
 m_hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,sizeof(TCHAR)*128, 이벤트아이디2); //invalid_handle_value로 생성시 메모리가 되어준다.

 if(::GetLastError() == ERROR_ALREADY_EXISTS){ //이미존재하면 권한다 먹고 오픈하자.
  m_hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,이벤트아이디2);
 }

 if( m_hMap == NULL){
  AfxMessageBox(_T("Error:Cannot open file Mapping obj."));
  return FALSE;
 }

 //MapViewOfFile의 리턴값은 file의 핸들의 주소. 그걸 카피하면 그냥 복사하는거다.
 //이걸 잘 활용하면 그냥 복사해도 되고 잘만써먹으면 바로 폰에 뿌려줄수도있다.(중간에캐스팅하고). 주의사항 ::CreateFileMapping에서 생성된 것과 ::MapViewOfFile의 크기는 같아야한다.
 //적어도 전자가 더 길어야 오류는 안난다. 이 둘은 한 세트임.
 m_pSharedMemory = (TCHAR*)::MapViewOfFile(m_hMap,FILE_MAP_ALL_ACCESS,0,0,sizeof(TCHAR)* 128);

 if( m_pSharedMemory == NULL){
  AfxMessageBox(_T("Error:Failed to get Shared Mem."));
  return FALSE;
 }

 return TRUE;
}

-ExitInstance
int CSharedmemdemoApp::ExitInstance()
{
  if(m_pSharedMemory != NULL){
    ::UnmapViewOfFile(m_pSharedMemory);
  }
  if( m_hMap != NULL){
    ::CloseHandle(m_hMap);
  }

  m_ExitEvent.SetEvent();
  ::Sleep();
  return CWinApp::ExitInstance();
}

-InitInstance내부
if(!InitSharedMemory()){
  return FALSE;
}
AfxBeginThread(CSharedMemDemoApp::ThreadReadSharedMemory,NULL);
추가할것.

*중요한점 : 커널 객체의 이름은 항상 유일해야한다!!! 같게해놓으면 실행삽질이 난다.

*다이얼로그에서..
LRESULT CSharedmemdemoDlg::OnRecvEvent(WPARAM wParam, LPARAM lParam)
{
 m_ctlListbox.InsertString(0,theApp.m_pSharedMemory);
 return 0;
}

*write하기
void CSharedmemdemoDlg::OnButton()
{
 if( (!UpdateData(TRUE)) || (m_editStr.IsEmpty() == TRUE)){
  return;
 }
 if(theApp.m_Mutex.Lock(1000)){
  CEvent EventSend(FALSE,TRUE,U_RDEVENTNAME);
  //manual set을하는 이유는 Sleep걸고나서 새로이세팅되면 무한한 루프에빠질수있다.
  wsprintf(theApp.m_pSharedMemory,_T("%s"),m_editstr);
  EventSend.SetEvent();
  ::Sleep(1);
  EventSend.ResetEvent();
 } 
 theApp.m_Mutex.Unlock();
 }
 else{
  AfxMessageBox(_T("Error:Lock() return FALSE!"));
  return;
 }

 m_editStr = _T("");
 UpdateData(FALSE);
}

*여기까지한일을 살펴보자
 1)Initinstance : 공유메모리초기화
 2)InitInstance : 스레드 시작 및 이벤트 두개 감시(종료/공유메모리로 문자열수신)
 3)메시지전송 -> 대화상자 : 리스트박스에 문자열추가.
 4)Writing : 실제 메모리에 집어넣는다.

*동기화는 항상 Sleep이 아닌 Recv Event를 이용하라!

*이 방법은 보내고 땡이지만... 실제로 고속의 송/수신을 위해서는 recv이벤트를 만들어서 날려주어야한다. 물론 그만큼 설계를 변경해야한다. 이것을 해주어야 더 좋은 성능을 낼 수 있다.
 물론 단일 UI의 경우다. 만약 이것이 많아진다면.. 다 맞추어 설계해야한다. 동기화 고려가 골아프다. 그럴라면 소켓을 쓰자. 동기화 깨질 문제가 없다. 근데.. 고려해볼 사항이 추가된다. 방화벽이켜져있으면 허용여부를 결정해야한다. -> 방화벽 자체는 COM객체이므로 이놈한테 붙어서 내 프로세스를 허용하도록 등록해야한다.

*127.0.0.1 : TDI레벨까지밖에 내려가지않는다.

반응형

댓글