블로그 이미지
ludwings

카테고리

분류 전체보기 (132)
WIN API (22)
워게임 (61)
만든것 (2)
메모 (39)
Total17,406
Today16
Yesterday3

작업관리자에서 메모장 종료하는 것을 막아보도록 terminateprocess를 후킹해봤다..

 

처음에 안됬던게 TerminateProcess(HANDLE hProcess, UINT uExitCode) 에서

 

hProcess를 이용하여 getprocessid 를 사용해 종료하려고 하는 프로세스의 id를 구해보려고 했으나 자꾸 0이 리턴 되었다..

 

알고보니 이 hProcess의 값은 작업관리자에서 OpenProcess 해줄때 옵션을 PROCESS_TERMINATE를 주어서 이 핸들로는  아무런 정보도 건지지 못한 것이고.. duplicatehandle을 사용하여 복사해준뒤 getprocessid를 사용하니까 정상적으로 동작했다.

 

정보 : http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=50&MaeulNo=20&no=487716&ref=487336

 

 

/*hook_terminateprocess code*/
#include 
#include 

#include 

#define DEF_PROCNAMEW L"notepad.exe"
#define DEF_KERNEL32 "Kernel32.dll"
#define DEF_TERMINATEPROCESS "TerminateProcess"

// global variable
BYTE g_pOrgBytes[5] = {0,};


DWORD CheckProcess(LPCTSTR szProcessName)
{
	HANDLE hSnapShot = INVALID_HANDLE_VALUE;
	PROCESSENTRY32 pe;
	DWORD dwPID;
	pe.dwSize = sizeof(PROCESSENTRY32);

	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

	Process32First(hSnapShot, &pe);

	do 
	{
		dwPID = pe.th32ProcessID;
		if(dwPID < 100)
			continue;

		if(!lstrcmp(pe.szExeFile, szProcessName)) // 찾고자하는 프로세스가 있으면 
			return dwPID;

	} while (Process32Next(hSnapShot, &pe));

	CloseHandle(hSnapShot);

	return 0;
}

BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)
{
	FARPROC pfnOrg;
	DWORD dwOldProtect, dwAddress;
	BYTE pBuf[5] = {0xE9, 0, };
	PBYTE pByte;

	// 후킹 대상 API 주소를 구한다
	pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
	pByte = (PBYTE)pfnOrg;

	// 만약 이미 후킹 되어 있다면 return FALSE
	if( pByte[0] == 0xE9 )
		return FALSE;

	// 5 byte 패치를 위하여 메모리에 WRITE 속성 추가
	VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

	// 기존 코드 (5 byte) 백업
	memcpy(pOrgBytes, pfnOrg, 5);

	// JMP 주소 계산 (E9 XXXX)
	// => XXXX = pfnNew - pfnOrg - 5
	dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5;
	memcpy(&pBuf[1], &dwAddress, 4);

	// Hook - 5 byte 패치 (JMP XXXX)
	memcpy(pfnOrg, pBuf, 5);

	// 메모리 속성 복원
	VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);

	return TRUE;
}

BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
{
	FARPROC pFunc;
	DWORD dwOldProtect;
	PBYTE pByte;

	// API 주소 구한다
	pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
	pByte = (PBYTE)pFunc;

	// 만약 이미 언후킹 되어 있다면 return FALSE
	if( pByte[0] != 0xE9 )
		return FALSE;

	// 원래 코드(5 byte)를 덮어쓰기 위해 메모리에 WRITE 속성 추가
	VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

	// Unhook
	memcpy(pFunc, pOrgBytes, 5);

	// 메모리 속성 복원
	VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);

	return TRUE;
}

typedef BOOL (WINAPI *PFTERMINATEPROCESS)(HANDLE hProcess, UINT uExitCode);

BOOL WINAPI MyTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
	FARPROC pFunc;
	unhook_by_code(DEF_KERNEL32, DEF_TERMINATEPROCESS, g_pOrgBytes);
	BOOL bRet;
	
	DWORD dwnotepadid = CheckProcess(DEF_PROCNAMEW);
	DWORD dwcurrentid;
	
	HANDLE outprocess;
	BOOL bRet= DuplicateHandle(GetCurrentProcess(), hProcess, GetCurrentProcess(), &outprocess, PROCESS_ALL_ACCESS, FALSE, 0);

	if(bRet)
	{
		dwcurrentid = GetProcessId(outprocess);
		bRet = FALSE;
	}
	else
	{
		goto __MYTERMINATEPROCESS_END;
	}


	if(dwnotepadid == dwcurrentid) // notepad. exe에 주입할거니까 ㅋㅋ
	{
		bRet = FALSE;
		goto __MYTERMINATEPROCESS_END;
	}

	pFunc = GetProcAddress(GetModuleHandleA(DEF_KERNEL32), DEF_TERMINATEPROCESS);

	bRet = ((PFTERMINATEPROCESS)pFunc)(hProcess, uExitCode);
	
__MYTERMINATEPROCESS_END:
	hook_by_code(DEF_KERNEL32, DEF_TERMINATEPROCESS, (PROC)MyTerminateProcess, g_pOrgBytes);

	return bRet;
}

BOOL WINAPI DllMain( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved )
{
	switch(dwReason)
	{
	case DLL_PROCESS_ATTACH:
		hook_by_code(DEF_KERNEL32, DEF_TERMINATEPROCESS, 
			(PROC)MyTerminateProcess, g_pOrgBytes);
		break;
	case DLL_PROCESS_DETACH:		
		unhook_by_code(DEF_KERNEL32, DEF_TERMINATEPROCESS, 
			g_pOrgBytes);
		break;
	}
	return TRUE;
}
Posted by ludwings

댓글을 달아 주세요

  1. 2014.01.10 15:41 신고 QBeom  댓글주소  수정/삭제  댓글쓰기

    소스 변수명들이 극-혐이네요

/*
시스템 수준의 디버깅 목적으로 제공된다..

This privilege allows the caller all access to the process, including the ability to call TerminateProcess(),
CreateRemoteThread(), and other potentially dangerous Win32 APIs on the target process.

보안상의 이유로 액세스 토큰을 사용한다.
이 권한을 상승 시키기 위해서
1. openprocesstoken() with TOKEN_ADJUST_PRIVILEGE and TOKEN_QUERY flags
2. LookupPrivilegeValue() to get the LUID of the privilege i want to adjust
3. AdjustTokenPrivileges() to adjust the Tokens
4. DO whatever
5. Call AdjustTokenPrivileges() again to set the old privileges back
6. close the token handle
*/

#define RTN_USAGE 1
#define RTN_ERROR 13

#include 
#include 

BOOL SetPrivilege(
	HANDLE hToken,          // token handle
	LPCTSTR Privilege,      // Privilege to enable/disable
	BOOL bEnablePrivilege   // TRUE to enable.  FALSE to disable
	);

void DisplayError(LPTSTR szAPI);

int main(int argc, char *argv[])
{
	HANDLE hProcess;
	HANDLE hToken;
	int dwRetVal=RTN_OK; // assume success from main()

	// show correct usage for kill
	if (argc != 2)
	{
		fprintf(stderr,"Usage: %s [ProcessId]\n", argv[0]);
		return RTN_USAGE;
	}

	if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
	{
		if (GetLastError() == ERROR_NO_TOKEN)
		{
			if (!ImpersonateSelf(SecurityImpersonation))
				return RTN_ERROR;

			if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){
				DisplayError("OpenThreadToken");
				return RTN_ERROR;
			}
		}
		else
			return RTN_ERROR;
	}

	// enable SeDebugPrivilege
	if(!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
	{
		DisplayError("SetPrivilege");

		// close token handle
		CloseHandle(hToken);

		// indicate failure
		return RTN_ERROR;
	}

	// open the process
	if((hProcess = OpenProcess(
		PROCESS_ALL_ACCESS,
		FALSE,
		atoi(argv[1]) // PID from commandline
		)) == NULL)
	{
		DisplayError("OpenProcess");
		return RTN_ERROR;
	}

	// disable SeDebugPrivilege
	SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);

	if(!TerminateProcess(hProcess, 0xffffffff))
	{
		DisplayError("TerminateProcess");
		dwRetVal=RTN_ERROR;
	}

	// close handles
	CloseHandle(hToken);
	CloseHandle(hProcess);

	return dwRetVal;
}
BOOL SetPrivilege(
	HANDLE hToken,          // token handle
	LPCTSTR Privilege,      // Privilege to enable/disable
	BOOL bEnablePrivilege   // TRUE to enable.  FALSE to disable
	)
{
	TOKEN_PRIVILEGES tp;
	LUID luid;
	TOKEN_PRIVILEGES tpPrevious;
	DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);

	if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE;

	// 
	// first pass.  get current privilege setting
	// 
	tp.PrivilegeCount           = 1;
	tp.Privileges[0].Luid       = luid;
	tp.Privileges[0].Attributes = 0;

	AdjustTokenPrivileges(
		hToken,
		FALSE,
		&tp,
		sizeof(TOKEN_PRIVILEGES),
		&tpPrevious,
		&cbPrevious
		);

	if (GetLastError() != ERROR_SUCCESS) return FALSE;

	// 
	// second pass.  set privilege based on previous setting
	// 
	tpPrevious.PrivilegeCount       = 1;
	tpPrevious.Privileges[0].Luid   = luid;

	if(bEnablePrivilege) {
		tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
	}
	else {
		tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
			tpPrevious.Privileges[0].Attributes);
	}

	AdjustTokenPrivileges(
		hToken,
		FALSE,
		&tpPrevious,
		cbPrevious,
		NULL,
		NULL
		);

	if (GetLastError() != ERROR_SUCCESS) return FALSE;

	return TRUE;
}
BOOL SetPrivilege( 
	HANDLE hToken,  // token handle 
	LPCTSTR Privilege,  // Privilege to enable/disable 
	BOOL bEnablePrivilege  // TRUE to enable. FALSE to disable 
	) 
{ 
	TOKEN_PRIVILEGES tp = { 0 }; 
	// Initialize everything to zero 
	LUID luid; 
	DWORD cb=sizeof(TOKEN_PRIVILEGES); 
	if(!LookupPrivilegeValue( NULL, Privilege, &luid ))
		return FALSE; 
	tp.PrivilegeCount = 1; 
	tp.Privileges[0].Luid = luid; 
	if(bEnablePrivilege) { 
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
	} else { 
		tp.Privileges[0].Attributes = 0; 
	} 
	AdjustTokenPrivileges( hToken, FALSE, &tp, cb, NULL, NULL ); 
	if (GetLastError() != ERROR_SUCCESS) 
		return FALSE; 

	return TRUE;
}
void DisplayError(
	LPTSTR szAPI    // pointer to failed API name
	)
{
	LPTSTR MessageBuffer;
	DWORD dwBufferLength;

	fprintf(stderr,"%s() error!\n", szAPI);

	if(dwBufferLength=FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,
		GetLastError(),
		GetSystemDefaultLangID(),
		(LPTSTR) &MessageBuffer,
		0,
		NULL
		))
	{
		DWORD dwBytesWritten;

		// 
		// Output message string on stderr
		// 
		WriteFile(
			GetStdHandle(STD_ERROR_HANDLE),
			MessageBuffer,
			dwBufferLength,
			&dwBytesWritten,
			NULL
			);

		// 
		// free the buffer allocated by the system
		// 
		LocalFree(MessageBuffer);
	}
}
Posted by ludwings

댓글을 달아 주세요

winapi] 64bit dll injector

WIN API / 2014. 1. 8. 23:58

이거도해봐야지...

 

지금 dll injector는 32bit dll을ㅇ 32bit process에 인젝트하는 것만 ㄷ ㅗ ㅣ는데..

 

아니근데 64비트 dll은 어케 만드는거지? 구성관리자에서 x64로 해놓고 컴파일해도 32비트로 생성되는데 dll이?

 

일단 64bit 프로세스 만들어보고 64bit dll 만들어본 다음에 인젝션 시켜봐야지...

 

우선 reversecore에서 64bit injector하고 64bit dll 가져와서 실험해봣다.. 그런데 fail한다 ㅋㅋ 일단 dll은 64bit가 맞으니 injector에 문제가 있는거 같고

 

내가 만든 32bit에서 되던 dll injector로 reversecore에서 가져온 dummy64.dll 을 64bit 메모장에 인젝션 시도해봤는데 안된다 .. 그렇다 나의 인젝터에도 문제가 있었던 것이다..

 

그렇다면 할일..

1. 테스트용으로 64bit 프로세스 만들어보고

2. 64bit dll 만들어내고

3. 인젝터 수정하거나 만들기

 

--

 

1. 64프로세스 됨

 

 

 

2. 근데 64bit dll 이면 이런창 한번 떠야하는데

 

 

 

x64로 설정하고 해도 안뜸ㅋㅋ

 

ㅅㅂ 알고보니까 개삽질이야 프로젝트\debug\64.dll 이 아니라 프로젝트\x64\debug\64.dll 여기 들어있었네 ㅋㅋㅋㅋㅋㅋㅋ 이힣ㅅ

 

3.인젝터는..

'WIN API' 카테고리의 다른 글

cpp 객체리턴 액세스 위반 에러  (6) 2015.04.28
winapi] 64bit dll injector  (2) 2014.01.08
win api] lol 실행 차단  (0) 2014.01.02
Dll Injector, Dll Ejector  (0) 2013.10.11
#pragma once  (0) 2013.09.04
WINAPI ] 간단한 채팅2  (0) 2013.05.07
Posted by ludwings

댓글을 달아 주세요

  1. 2014.03.27 02:17 고구마  댓글주소  수정/삭제  댓글쓰기

    저도 안되서 계속 코드 수정하고 컴파일하고 ... 결국 님 블로그 보고 알게 됐어요.

    x64 폴더가 따로 있더라는........... -_- 삽질 멈추게 해줘서 고맙습니다!

최근에 달린 댓글

최근에 받은 트랙백

글 보관함