https://saevo.online/  

해외(?)에서 디스코드 서버로 운영하고 있는 서든어택인데 생각보다 잘만들어서 분석을 해봤다.

별도의 anticheat도 존재했으며 Themida 패킹, 코드 가상화 기법까지 사용했음

 

anticheat의 로직은 nexon의 blackcipher와 유사도가 있었음.

다른 게임의 anticheat들도 이와 같은 방식이거나 다른 방식으로 무력화 시킬 수 있다.

 

 

1. 별도 launcher와 clinet가 존재함 >> discord_game_sdk를 사용해 token을 얻어 unique값으로 활용함

discord 연동

 

 

2. launcher에서는 현재 파일들을 hash, size를 검사해 무결성 검사를 한다. 변조가 되었을 시 해당 서버에서 받아옴. 

   Themida 패킹을 해놓았기 때문에 동적으로 무력화를 해야함.

launcher 로직1
launcher 로직2

 

3. anticheat는 2개의 파일이 존재하며 로그, 설정파일은 암호화시켜 작성 후 서버로 전송시킴.

anticheat file
Themida

 

4.  AHT_Main.dll의 export 함수 중 "Ordinal2"는 실제 행위를 하는 주소이며, VirtualAlloc을 통해 임의의 주소값으로 CRC 행위를 수행한다.

AHT_Main.dll_Ordinal2 Thread

5.  AntiHackTool.dll은 AHT_Main과 같이 VirtualAlloc을 사용해 임의의 주소값으로 AHT_Main의 CRC 검사를 진행한다.

AntiHackTool.dll Thread

6.  Clinet 내부의 anticheat, cshell.dll, d3d, 등 code의 변조를 실시간 감지함.

CRC

7. anticheat들의 return back trace를 살펴보면 호출 흐름을 파악 가능하다. esp trick을 이용해 무력화를 진행한다.

   Sleep 함수 호출 전 esp의 값은 return address가 담기는데 해당 주소를 수행하지 못하게 변경해주는 것이다.

 

# 참고로 Win7이후 kernel32의 API를 호출 시 Kernel32.dll!Sleep > KernelBase.dll!Sleep으로 jmp 후 호출한다.

esp trick

 

8. 위의 방식을 토대로 Code Injection을 해주면 된다. 간단한 Cheat Engine Script로 제작했는데 dll으로 제작해봐야겠당

 

   # 이전에 CRC를 통해 변조를 감지한다고 설명 했었는데 CRC는 내부 모듈의 대해서만 검사를 하므로 system 내의 있      는 모듈의 대해서는 검사를 못한다.

 

이것저것 하는게 너무 재밌어서 이제 악분도 다시 해야겠음..

궁금하신게 있거나 틀린점이 있으면 지적해주십쇼!

'Develop > C, CheatEngine' 카테고리의 다른 글

Five M Cheat Engine Bypass  (4) 2021.09.29
debugge, debugger  (0) 2021.09.28

Fivem Cheat Engine Bypass

 

Fivem은 현재 Windows Station안에 있는 Process를 찾고 CreateFile, ReadFile,GetFileAttributes 등 API를 사용해 패턴 매칭을 하는 것 같다.

 

우회 순서는 Cheat Engine을 실행 후 권한 변경을 통해 Fivem이 탐지 API를 무력화 시키는것임..

 

 

로직의 흐름은 SID 생성하고 권한 할당 후 적용 시키는 방식이다.

 

자료가 많이 없어 좀 해맸다.. 항상 성공하면 뿌듯~ㅋ

 

# AllocateAndInitializeSid

# SetEntriesInAcl

# SetSecurityInfo

 

나중에 까먹을까봐 메모

 

사용 하실분은 쓰세요 궁금하신건 댓글 달아 주세영

#include <windows.h>
#include <stdio.h>
#include <AclAPI.h>
#include <tchar.h>

#pragma comment(lib, "advapi32.lib")

BOOL CreateDirectoryWithUserFullControlACL(LPCTSTR lpPath)
{
    STARTUPINFO si = { 0, };
    PROCESS_INFORMATION pi;

    BOOL CreaP = CreateProcess(lpPath, NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    if (CreaP == 0)
    {
        printf("[*]Create Process Faile\n");
        printf("[*]ERROR CODE: %0x%X\n", GetLastError());
        return FALSE;
    }
    printf("[*]Create Success\n");

    HANDLE hDir = CreateFile(lpPath, READ_CONTROL | WRITE_DAC, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (hDir == INVALID_HANDLE_VALUE)
    {
        printf("[*]Create File Fail\n");
        printf("[*]ERROR CODE: %0x%X\n", GetLastError());
        return FALSE;
    }
    printf("[*]Create File Success\n");

    SECURITY_DESCRIPTOR* pSD = NULL;
    DWORD dwRes;
    PSID pEveryoneSID = NULL, pAdminSID = NULL, pUserSID = NULL;
    EXPLICIT_ACCESS ea[2];
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;

    PACL pACL = NULL;

    if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
        SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0,
        &pAdminSID))
    {
        _tprintf(_T("[*]AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto CleanUp;
    }

    ea[0].grfAccessPermissions = GENERIC_ALL;
    ea[0].grfAccessMode = DENY_ACCESS;
    ea[0].grfInheritance = NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[0].Trustee.ptstrName = (LPTSTR)pAdminSID;

    if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
        SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_USERS,
        0, 0, 0, 0, 0, 0,
        &pUserSID))
    {
        _tprintf(_T("[*]AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto CleanUp;
    }

    ea[1].grfAccessPermissions = GENERIC_ALL;
    ea[1].grfAccessMode = DENY_ACCESS;
    ea[1].grfInheritance = NO_INHERITANCE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName = (LPTSTR)pUserSID;

    dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
    if (dwRes != ERROR_SUCCESS)
    {
        _tprintf(_T("[*]SetEntriesInAcl Error %u\n"), GetLastError());
        goto CleanUp;
    }
    if (pACL)
        SetSecurityInfo(hDir, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL);

    return TRUE;

CleanUp:
    if (pAdminSID)
        FreeSid(pAdminSID);
    if (pEveryoneSID)
        FreeSid(pEveryoneSID);
    if (pUserSID)
        FreeSid(pUserSID);
    return FALSE;
}
    
int main(int argc, char** argv) {
    if (argv[1] == NULL)
    {
        printf("[*]Invaild Argument.. Input Path\n");
        return -1;
    }
   printf("[*]Path: %s\n", argv[1]);
   BOOL status = CreateDirectoryWithUserFullControlACL(argv[1]);
   if (status == TRUE) 
   {
       printf("[*]Complete\n");
       return 0;
   }
   else 
   {
       printf("[*]Faile\n");
       return -1;
   }
   
}

 

 

 

 

# Reference

https://docs.microsoft.com/en-us/windows/win32/api/accctrl/ns-accctrl-explicit_access_a

 

EXPLICIT_ACCESS_A (accctrl.h) - Win32 apps

Defines access control information for a specified trustee.

docs.microsoft.com

https://deguls.tistory.com/entry/DACL%EA%B3%BC-SACL-%EB%B3%B5%EC%8A%B5

 

DACL과 SACL 복습

출처: http://blog.naver.com/knuabhoony?Redirect=Log&logNo=40014321712 일반적으로 ACL 이라고만 하면 DACL를 뜻함. DACL = discretionary access control list SACL = security access control list DACL에는..

deguls.tistory.com

https://docs.microsoft.com/en-us/windows/win32/fileio/file-security-and-access-rights

 

File Security and Access Rights - Win32 apps

Because files are securable objects, access to them is regulated by the access-control model that governs access to all other securable objects in Windows.

docs.microsoft.com

 

'Develop > C, CheatEngine' 카테고리의 다른 글

saevo 서든어택 anticheat-bypass  (3) 2021.10.06
debugge, debugger  (0) 2021.09.28

예전에 공부하면서 만들어 뒀던 코드임

powershell을 debugge로 걸어두고 cmdline을 실시간 탐지해 Fileless Malware를 탐지했다.

 

#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "tlhelp32.h"
#include "TCHAR.H"
#include "string.h"

#pragma warning(disable : 4996)
#define DEF_PROC_NAME ("powershell.exe")

char* Adr_cmdline, *Adr_copy, *Adr_ori;
CREATE_PROCESS_DEBUG_INFO g_cpdi;
BYTE OP_BP = 0xCC, OP_Ret = 0xC3;
DWORD dwPID = 0xFFFFFFFF;
LPVOID Adr_original = NULL;
DWORD WINAPI FindProcessID(LPCSTR szProcname);
void DebugLoop();
int main()
{

	DWORD dwThrdParam;
	DWORD dwThreadId;

	HANDLE hThread = CreateThread(NULL, 0, FindProcessID, &dwThrdParam, 0, &dwThreadId);

	dwPID = FindProcessID(DEF_PROC_NAME);

	if (!DebugActiveProcess(dwPID))
	{

		return 1;

	}
	DebugLoop();
}

void DebugLoop()
{

	DEBUG_EVENT de;
	DWORD dwContinueStatus;

	while (WaitForDebugEvent(&de, INFINITE))
	{
		dwContinueStatus = DBG_CONTINUE;

		if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)
		{
			OnCreateProcessDebugEvent(&de);

		}
		else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode)
		{
			if (OnExceptionDebugEvent(&de))
				continue;


		}
		else if (EXIT_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)
		{
			break;
		}
		ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
	}
}


BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde)
{
	DWORD dwAddrOfBuffer;

	Adr_cmdline = GetProcAddress(GetModuleHandle("kernelbase.dll"), "GetCurrentProcess");
	Adr_original = GetProcAddress(GetModuleHandle("kernelbase.dll"), "GetCurrentProcess");

	Adr_copy = Adr_cmdline - 6;

	VirtualProtect(Adr_copy, 10, PAGE_EXECUTE_READWRITE, &dwAddrOfBuffer);

	memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));

	ReadProcessMemory(g_cpdi.hProcess, Adr_copy, &OP_Ret, 1, NULL);
	WriteProcessMemory(g_cpdi.hProcess, Adr_copy, &OP_BP, 1, NULL); 

	printf("\n[ Install BreakPoint ]  Address : 0x%p OPCODE : 0xC3 -> 0xCC Patched\n", Adr_copy);


	return TRUE;
}

BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pde)
{
	CONTEXT ctx;
	DWORD dwNumOfBytesToCompare;
	PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord;
	char* str = NULL, buffer = NULL, result = NULL;
	SIZE_T bytesRead;

	if (EXCEPTION_BREAKPOINT == per->ExceptionCode)
	{
		if (Adr_copy == per->ExceptionAddress)
		{

			ctx.ContextFlags = CONTEXT_ALL;
			GetThreadContext(g_cpdi.hThread, &ctx);
			WriteProcessMemory(g_cpdi.hProcess, &Adr_copy, &OP_Ret, sizeof(BYTE), NULL);
			ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Eax), &buffer, 1000, &bytesRead);

			Adr_ori = Adr_copy - 5;

			wprintf(L"Command Line : %s\n", &buffer);

			if ((str = wcsstr(&buffer, L"$env")) == NULL)
			{
				MessageBox(NULL, TEXT("Normal"), TEXT("Alert"), MB_OK | MB_TOPMOST);
				return TRUE;
			}
			else
			{
				MessageBox(NULL, TEXT("malicious String : '$' Detected"), TEXT("Warning"), MB_OK | MB_TOPMOST);
				exit(1);

			}

			if ((str = wcsstr(&buffer, L"iex")) == NULL) 
			{
				MessageBox(NULL, TEXT("Normal"), TEXT("Alert"), MB_OK | MB_TOPMOST);
				return TRUE;
			}
			else
			{
				MessageBox(NULL, TEXT("malicious String : 'iex' Detected"), TEXT("Warning"), MB_OK | MB_TOPMOST);
				exit(1);

			}

			ctx.Eip = (DWORD)Adr_ori;
			SetThreadContext(g_cpdi.hThread, &ctx);

			ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);
			Sleep(0);

			return TRUE;
		}

	}

	return FALSE;

}

DWORD WINAPI FindProcessID(LPCSTR szProcname)
{
	while (1) {

		HANDLE hSnapShot = INVALID_HANDLE_VALUE;
		PROCESSENTRY32 pe;
		szProcname = "powershell.exe";

		pe.dwSize = sizeof(PROCESSENTRY32);
		hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

		Process32First(hSnapShot, &pe);
		do
		{
			if (!strcmp(szProcname, pe.szExeFile))
			{
				dwPID = pe.th32ProcessID;
				goto end;
			}

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

		WaitForSingleObject(hSnapShot, INFINITE);
	}
end:
	return dwPID;
}

'Develop > C, CheatEngine' 카테고리의 다른 글

saevo 서든어택 anticheat-bypass  (3) 2021.10.06
Five M Cheat Engine Bypass  (4) 2021.09.29

peid, exeinfo 툴에서 제공하는 packer signature 이다. 

 

yara로 탐지하기 위해 변환을 해준다.

 

# signature format 

[exepack]
signature = 60 68 ?? ?? ?? ?? B8 ?? ?? ?? ?? FF 10
ep_only = true
original = "ExE Pack" {V1.0} -> 'Elite Coding Group'

 

format은 편한데로 지정하면 된다

 

정규표현식으로 파싱을 했으므로 format에 맞춰 변경하면된다.

 

.yar

 

'Develop > python' 카테고리의 다른 글

Windows 이벤트 탐지  (0) 2020.08.10

Windows 이벤트 기반 동적분석용 이벤트 탐지

악성코드 분석용 한번에 여러 이벤트를 모니터링 목적으로 제작

 

 

# configure.conf


# Registry

 - configure.conf 파일을 load후 레지스트리의 원본과 새로운 레지스트리 값을 배열에 담아 중복비교

 


# Socket

  - 원본과 새로운값을 배열에 담아 중복비교

 


# File

  - watchdog 모듈을 이용해 확장자 패턴매칭 후 실시간 파일 생성, 삭제를 탐지

 

'Develop > python' 카테고리의 다른 글

PEID to YARA  (0) 2021.02.23

+ Recent posts