* ::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레벨까지밖에 내려가지않는다.
댓글