This commit is contained in:
Huoji's
2021-02-24 16:21:29 +08:00
parent a89ec73aa2
commit 382b21df20
3 changed files with 27 additions and 381 deletions

View File

@@ -266,7 +266,7 @@ void WalkProcessMoudle(DWORD pID,HANDLE pHandle,WCHAR* pMoudleName) {
FoundNum++;
}
if (FoundNum > 1) {
printf("\t => [<5B><><EFBFBD>̼<EFBFBD><CCBC><EFBFBD>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(.rdata<74><61>ɱ or <20>ӿdz<D3BF><C7B3><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %ws <EFBFBD><EFBFBD><EFBFBD><EFBFBD>id %d ģ<><C4A3><EFBFBD><EFBFBD> %ws <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %s \n", pMoudleName, moduleEntry.szExePath, pID, SectionHeader[i].Name);
printf("\t => [<5B><><EFBFBD>̼<EFBFBD><CCBC><EFBFBD>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(.rdata<74><61>ɱ or <20>ӿdz<D3BF><C7B3><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %ws ·<EFBFBD><EFBFBD> %ws <20><><EFBFBD><EFBFBD>id %d\n", pMoudleName, moduleEntry.szExePath, pID);
break;
}
}

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# DuckMemoryScan
一个简单寻找无文件落地后门的工具,由huoji花了1天编写,编写时间2021-02-24
# 功能列表
1. HWBP hook检测 检测线程中所有疑似被hwb挂钩
2. 内存免杀shellcode检测(metasploit,Cobaltstrike完全检测)
3. 可疑进程检测(主要针对有逃避性质的进程[如过期签名与多各可执行区段])
4. 无文件落地木马检测(检测所有已知内存加载木马)
5. 简易rootkit检测(检测证书过期/拦截读取/证书无效的驱动)
# 免杀木马检测原理:
所有所谓的内存免杀后门大部分基于"VirtualAlloc"函数申请内存 之后通过各种莫名其妙的xor甚至是aes加密去混淆shellcode达到"免杀"效果.
本工具通过线程堆栈回溯方法(StackWalkEx函数)遍历线程,寻找系统中在VirtualAlloc区域执行代码的区域,从而揪出"免杀木马"
当然也会存在误报,多常见于加壳程序也会申请VirtualAlloc分配内存.
# 无文件落地木马检测原理:
所有无文件落地木马都是一个标准PE文件被映射到内存中,主要特征如下:
1. 内存区段有M.Z标志
2. 线程指向一个NOIMAGE内存
本工具将会通过第一种特征检测出所有"无文件落地木马"
# 使用方式
编译 运行 得到信息列表
# 追踪这个项目
https://key08.com

View File

@@ -1,380 +0,0 @@
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <psapi.h>
#include <shlwapi.h>
#include <string.h>
#include <wchar.h>
#include <dbghelp.h>
#pragma comment(lib,"dbghelp.lib")
#include "tlhelp32.h"
#include "CdigitalSig.h"
BOOL Is64BitPorcess(HANDLE hProcess)
{
BOOL bIsWow64 = false;
IsWow64Process(hProcess, &bIsWow64);
return bIsWow64 == false;
}
BOOL EnableDebugPrivilege(BOOL bEnable)
{
//Enabling the debug privilege allows the application to see
//information about service application
BOOL fOK = FALSE; //Assume function fails
HANDLE hToken;
//Try to open this process's acess token
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
//Attempt to modify the "Debug" privilege
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOK = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOK;
}
void WCharToChar(const WCHAR* tchar, char* _char)
{
int iLength;
iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL);
}
void CharToWchar(const char* _char, WCHAR* tchar)
{
int iLength;
iLength = MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, tchar, iLength);
}
BOOL DosPathToNtPath(WCHAR* pszDosPath, LPTSTR pszNtPath)
{
TCHAR szDriveStr[500];
TCHAR szDrive[3];
TCHAR szDevName[100];
INT cchDevName;
INT i;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!pszDosPath || !pszNtPath)
return FALSE;
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
if (GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr))
{
for (i = 0; szDriveStr[i]; i += 4)
{
if (!lstrcmpi(&(szDriveStr[i]), L"A:\\") || !lstrcmpi(&(szDriveStr[i]), L"B:\\"))
continue;
szDrive[0] = szDriveStr[i];
szDrive[1] = szDriveStr[i + 1];
szDrive[2] = '\0';
if (!QueryDosDevice(szDrive, szDevName, 100))//<2F><>ѯ Dos <20><EFBFBD><E8B1B8>
return FALSE;
cchDevName = lstrlen(szDevName);
if (_wcsnicmp(pszDosPath, szDevName, cchDevName) == 0)//<2F><><EFBFBD><EFBFBD>
{
lstrcpy(pszNtPath, szDrive);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lstrcat(pszNtPath, pszDosPath + cchDevName);//<2F><><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
return TRUE;
}
}
}
lstrcpy(pszNtPath, pszDosPath);
return FALSE;
}
DWORD64 GetProcessMoudleHandle(DWORD pid) {
MODULEENTRY32 moduleEntry;
HANDLE handle = NULL;
handle = ::CreateToolhelp32Snapshot(0x00000008, pid);
ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
moduleEntry.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(handle, &moduleEntry)) {
CloseHandle(handle);
return NULL;
}
do {
CloseHandle(handle);
return (DWORD64)moduleEntry.hModule;
} while (Module32Next(handle, &moduleEntry));
return 0;
}
bool CheckThreadAddressIsExcute(DWORD64 pAddress,HANDLE pHandle, HANDLE pID, HANDLE Tid) {
DWORD64 ReadNum = 0;
MEMORY_BASIC_INFORMATION mbi = { 0 };
if (VirtualQueryEx(pHandle, (LPCVOID)pAddress, &mbi, sizeof(mbi)))
{
if (mbi.AllocationBase) {
if (mbi.Type != MEM_IMAGE) {
if (mbi.AllocationProtect & PAGE_EXECUTE ||
mbi.AllocationProtect & PAGE_EXECUTE_READ ||
mbi.AllocationProtect & PAGE_EXECUTE_READWRITE ||
mbi.AllocationProtect & PAGE_EXECUTE_WRITECOPY)
{
printf("\t => [<5B>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>] <20><><EFBFBD>⵽δ֪<CEB4>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>[VirtualAlloc<6F><63>ɱ?] <20><>ַ %p PID %d TID %d \n", pAddress, pID, Tid);
char PEStack[0x2];
if (ReadProcessMemory(pHandle, mbi.BaseAddress, PEStack, sizeof(PEStack), &ReadNum)) {
if (PEStack[0] == 'M' && PEStack[1] == 'Z') {
printf("\t => [!!!<21>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>!!!] <20><><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>س<EFBFBD><D8B3><EFBFBD> <20>̵߳<DFB3>ַ %p PID %d TID %d <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ַ: %p\n", pAddress, pID, Tid, mbi.BaseAddress);
}
}
return true;
}
}
}
}
return false;
}
void ThreadStackWalk() {
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
DWORD ExitCode = 0;
hThreadSnap = CreateToolhelp32Snapshot(0x00000004, GetCurrentProcessId());
if (hThreadSnap)
{
te32.dwSize = sizeof(THREADENTRY32);
if (!Thread32First(hThreadSnap, &te32))
{
CloseHandle(hThreadSnap);
return;
}
do
{
if (te32.th32OwnerProcessID != GetCurrentProcessId() && te32.th32ThreadID != GetCurrentThreadId())
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
if (hThread && hThread != (HANDLE)-1)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, te32.th32OwnerProcessID);
if (hProcess) {
STACKFRAME_EX StackFarmeEx;
memset(&StackFarmeEx, 0, sizeof(STACKFRAME_EX));
if (Is64BitPorcess(hProcess)) {
CONTEXT context = { 0 };
context.ContextFlags = CONTEXT_ALL;
if (GetThreadContext(hThread, &context))
{
if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3 != 0)
{
//hwbp hook
printf("\t => [<5B>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>] <20><><EFBFBD>⵽HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID);
}
CheckThreadAddressIsExcute(context.Rip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID);
StackFarmeEx.AddrPC.Offset = context.Rip;
StackFarmeEx.AddrPC.Mode = AddrModeFlat;
StackFarmeEx.AddrStack.Offset = context.Rsp;
StackFarmeEx.AddrStack.Mode = AddrModeFlat;
StackFarmeEx.AddrFrame.Offset = context.Rsp;
StackFarmeEx.AddrFrame.Mode = AddrModeFlat;
DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
while (true)
{
if (!StackWalkEx(machineType, hProcess, hThread, &StackFarmeEx, &context, NULL, NULL, NULL, NULL, NULL))
break;
if (StackFarmeEx.AddrFrame.Offset == 0)
break;
CheckThreadAddressIsExcute(StackFarmeEx.AddrPC.Offset, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID);
}
}
} else {
WOW64_CONTEXT context = { 0 };
context.ContextFlags = CONTEXT_ALL;
if (Wow64GetThreadContext(hThread, &context))
{
if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3 != 0)
{
//hwbp hook
printf("\t => [<5B>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>] <20><><EFBFBD>⵽HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID);
}
CheckThreadAddressIsExcute(context.Eip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID);
StackFarmeEx.AddrPC.Offset = context.Eip;
StackFarmeEx.AddrPC.Mode = AddrModeFlat;
StackFarmeEx.AddrStack.Offset = context.Esp;
StackFarmeEx.AddrStack.Mode = AddrModeFlat;
StackFarmeEx.AddrFrame.Offset = context.Ebp;
StackFarmeEx.AddrFrame.Mode = AddrModeFlat;
DWORD machineType = IMAGE_FILE_MACHINE_I386;//IMAGE_FILE_MACHINE_I386; IMAGE_FILE_MACHINE_AMD64;
while (true)
{
if (!StackWalkEx(machineType, hProcess, hThread, &StackFarmeEx, NULL, NULL, NULL, NULL, NULL, NULL))
break;
if (StackFarmeEx.AddrFrame.Offset == 0)
break;
CheckThreadAddressIsExcute(StackFarmeEx.AddrPC.Offset, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID);
}
}
}
CloseHandle(hProcess);
}
CloseHandle(hThread);
}
}
} while (Thread32Next(hThreadSnap, &te32));
CloseHandle(hThreadSnap);
}
}
void WalkProcessMoudle(DWORD pID,HANDLE pHandle,WCHAR* pMoudleName) {
MODULEENTRY32 moduleEntry;
HANDLE handle = NULL;
handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
moduleEntry.dwSize = sizeof(MODULEENTRY32);
char* AllocBuff = (char*)VirtualAlloc(NULL, 0x200, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (AllocBuff) {
if (!Module32First(handle, &moduleEntry)) {
CloseHandle(handle);
return;
}
do {
DWORD64 ReadNum = 0;
if (ReadProcessMemory(pHandle, moduleEntry.modBaseAddr, AllocBuff, 0x200, &ReadNum)) {
if (AllocBuff[0] == 'M' && AllocBuff[1] == 'Z') {
PIMAGE_DOS_HEADER CopyDosHead = (PIMAGE_DOS_HEADER)AllocBuff;
PIMAGE_NT_HEADERS CopyNthead = (PIMAGE_NT_HEADERS)((LPBYTE)AllocBuff + CopyDosHead->e_lfanew);
/*
DWORD64 BaseOfCode = 0;
DWORD64 SizeOfCode = 0;
if (CopyNthead->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
PIMAGE_NT_HEADERS64 CopyNthead64 = (PIMAGE_NT_HEADERS64)CopyNthead;
BaseOfCode = CopyNthead64->OptionalHeader.BaseOfCode;
SizeOfCode = CopyNthead64->OptionalHeader.SizeOfCode;
}
else {
PIMAGE_NT_HEADERS32 CopyNthead32 = (PIMAGE_NT_HEADERS32)CopyNthead;
BaseOfCode = CopyNthead32->OptionalHeader.BaseOfCode;
SizeOfCode = CopyNthead32->OptionalHeader.SizeOfCode;
}
*/
PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)CopyNthead + sizeof(CopyNthead->Signature) + sizeof(CopyNthead->FileHeader) + CopyNthead->FileHeader.SizeOfOptionalHeader);
int FoundNum = 0;
for (WORD i = 0; i < CopyNthead->FileHeader.NumberOfSections; i++)
{
if (SectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) {
FoundNum++;
}
if (FoundNum > 1) {
printf("\t => [<5B><><EFBFBD>̼<EFBFBD><CCBC><EFBFBD>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(.rdata<74><61>ɱ or <20>ӿdz<D3BF><C7B3><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %ws ģ<><C4A3><EFBFBD><EFBFBD> %ws <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %s \n", pMoudleName, moduleEntry.szExePath, SectionHeader[i].Name);
break;
}
}
}
}
} while (Module32Next(handle, &moduleEntry));
VirtualFree(AllocBuff, 0, MEM_RELEASE);
}
CloseHandle(handle);
}
void ProcessStackWalk() {
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot error.\n");
return;
}
BOOL bProcess = Process32First(hProcessSnap, &pe32);
while (bProcess)
{
//<2F><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>ID
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ProcessID);
if (hProcess) {
WalkProcessMoudle(pe32.th32ProcessID, hProcess, pe32.szExeFile);
WCHAR szImagePath[MAX_PATH];
WCHAR pszFullPath[MAX_PATH];
if (GetProcessImageFileName(hProcess, szImagePath, MAX_PATH))
{
if (DosPathToNtPath(szImagePath, pszFullPath))
{
CdigitalSig DigitalSig(pszFullPath);
DWORD dDigitalState = DigitalSig.GetDigitalState();
if (dDigitalState == DIGITAL_SIGSTATE_REVOKED || dDigitalState == DIGITAL_SIGSTATE_EXPIRE) {
printf("\t => [<5B><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ·<><C2B7> %ws static %d \n", pszFullPath, dDigitalState);
}
}
}
CloseHandle(hProcess);
}
bProcess = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return;
}
void ScanSystemDrivers() {
DWORD cbNeeded = 0; // drivers[] <20><><EFBFBD>ص<EFBFBD><D8B5>ֽ<EFBFBD><D6BD><EFBFBD>
LPVOID drivers[MAX_PATH] = { 0 }; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
int cDrivers = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Wow64EnableWow64FsRedirection(0);
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) // EnumDeviceDrivers <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ļ<EFBFBD><C4BC>ص<EFBFBD>ַ
{
char szDriver[MAX_PATH] = { 0 }; // <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
char szPath[MAX_PATH] = { 0 }; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ȫ·<C8AB><C2B7>
char szNtPath[MAX_PATH] = { 0 };
char szSystemPath[MAX_PATH] = { 0 }; // <20><><EFBFBD><EFBFBD> system32 <20>ļ<EFBFBD><C4BC><EFBFBD>·<EFBFBD><C2B7>
cDrivers = cbNeeded / sizeof(LPVOID); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < cDrivers; i++)
{
if (drivers[i]) {
if (GetDeviceDriverBaseNameA(drivers[i], szDriver, sizeof(szDriver) / sizeof(LPVOID)))
{
if (GetDeviceDriverFileNameA(drivers[i], szPath, sizeof(szPath))) {
bool isSystemDriver = true;
//ֻ<>жϷ<D0B6>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD>
if (szPath[1] == '?')
{
isSystemDriver = false;
int len = strlen(szPath);
szPath[len + 1] = '\0';
for (int j = 0; j < len; j++)
{
szPath[j] = szPath[j + 4];
}
WCHAR UnicodeFilePath[MAX_PATH << 1] = { 0 };
CharToWchar(szPath, UnicodeFilePath);
CdigitalSig DigitalSig(UnicodeFilePath);
DWORD dDigitalState = DigitalSig.GetDigitalState();
if (dDigitalState != DIGITAL_SIGSTATE_VALID) {
printf("\t => [<5B><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8>] <20><><EFBFBD>⵽δ֪<CEB4><D6AA><EFBFBD><EFBFBD> ·<><C2B7> %ws \n", UnicodeFilePath);
}
}
}
}
}
}
}
Wow64EnableWow64FsRedirection(1);
}
int main()
{
printf("DuckMemoryScan By huoji 2021-02-23 \n");
if (EnableDebugPrivilege(true) == false) {
printf("Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>,<2C><><EFBFBD>Թ<EFBFBD><D4B9><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \n");
system("pause");
return 0;
}
printf("<EFBFBD>̶߳<EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD><EFBFBD><EFBFBD> ... \n");
ThreadStackWalk();
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... \n");
ScanSystemDrivers();
printf("<EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD><EFBFBD><EFBFBD>... \n");
ProcessStackWalk();
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ... \n");
system("pause");
return 0;
}