/*
*
* This file is part of xspy
* By lynnux <lynnux@qq.com>
* Copyright 2013 lynnux
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "stdafx.h"
#include "common.h"
#include <string>
#include <codecvt>
#include <memory>
#include <vector>
#include <DbgHelp.h>
std::string GetMods(LPCVOID addr)
{
char tmp[MAX_PATH];
std::string s;
MEMORY_BASIC_INFORMATION mb = {0};
VirtualQuery(addr,&mb,sizeof(mb));
PBYTE pb = (PBYTE)mb.AllocationBase;
if(pb && pb[0] == 'M' && pb[1] == 'Z')
{
CHAR fn[MAX_PATH],*p;
fn[0] = 0;
GetModuleFileNameA((HMODULE)pb,fn,sizeof(fn));
p = strrchr(fn,'\\');
if (p)
{
++p;
} else
{
p = fn;
}
PIMAGEHLP_SYMBOL sym_info = (PIMAGEHLP_SYMBOL)malloc(sizeof(IMAGEHLP_SYMBOL) + MAX_PATH);
ZeroMemory(sym_info, sizeof(IMAGEHLP_SYMBOL) + MAX_PATH);
sym_info->Size = sizeof(IMAGEHLP_SYMBOL);
sym_info->MaxNameLength = MAX_PATH;
ULONG_PTR dwDisplament = 0;
g_Symbol->LoadModules_Base((HMODULE)pb);
if (SymGetSymFromAddr(GetCurrentProcess(), (ULONG_PTR)addr, &dwDisplament, sym_info))
{
std::string modname = p;
modname.resize(modname.find_last_of('.'));
// 当长度大于6时,%06p是不会截断显示的
_snprintf(tmp, MAX_PATH, "0x%p(%s+0x%06p -> %s!%s)", addr, p, ((PBYTE)addr - (PBYTE)pb), modname.c_str(), sym_info->Name);
s.assign(tmp);
}else
{
DWORD last_error = GetLastError();
printf("m_szSymPath:\r\nGetLastError:%d\r\n", last_error);
// 当长度大于6时,%06p是不会截断显示的
_snprintf(tmp, MAX_PATH, "0x%p(%s+0x%06p)", addr, p, ((PBYTE)addr - (PBYTE)pb));
s.assign(tmp);
}
//s.Format("%p(%s+%06X)",addr,p,(PBYTE)addr - (PBYTE)pb );
}
else
{
_snprintf(tmp, MAX_PATH,"0x%p", addr);
s.assign(tmp);
//s.Format("%p",addr);
}
return s;
}
static PVOID GetFinalAddr( PVOID addr )
{
if (addr==0)
{
return nullptr;
}
MEMORY_BASIC_INFORMATION mb = { 0 };
VirtualQuery(addr, &mb, sizeof(mb));
if (!(mb.Protect&(PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)))
{
return nullptr;
}
PBYTE pbaddr = (PBYTE)addr;
int changed = 0;
do
{
changed = 0;
if(pbaddr[0] == 0xe9)
{
pbaddr += 5 + *(PDWORD)(pbaddr+1);
changed = 1;
}
else if(pbaddr[0] == 0xff && pbaddr[1] == 0x25)
{
#ifndef _WIN64
pbaddr = **(PBYTE**)(pbaddr+2);
#else
pbaddr = pbaddr+ *(PDWORD)(pbaddr + 2) + 6;
changed = 1;
#endif
}
} while(changed);
return pbaddr;
}
std::string GetCodes(PVOID addr)
{
if (addr==0)
{
return std::string("");
}
char tmp[MAX_PATH];
PVOID pbaddr = GetFinalAddr(addr);
std::string s;
if(pbaddr != addr)
{
_snprintf(tmp, MAX_PATH, "0x%p -> ", addr);
s.assign(tmp);
//s.Format("%p->",addr);
}
s += GetMods(pbaddr);
return s;
}
//Char string to a Ansi string
std::string WChar2Ansi(LPCWSTR pwszSrc)
{
int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);
if (nLen <= 0) return std::string("");
char* pszDst = new char[nLen];
if (NULL == pszDst) return std::string("");
WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);
pszDst[nLen - 1] = 0;
std::string strTemp(pszDst);
delete[] pszDst;
return strTemp;
}
//Converting a Ansi string to WChar string
std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen)
{
int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);
if (nSize <= 0) return NULL;
WCHAR *pwszDst = new WCHAR[nSize + 1];
if (NULL == pwszDst) return NULL;
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, pwszDst, nSize);
pwszDst[nSize] = 0;
if (pwszDst[0] == 0xFEFF) // skip Oxfeff
for (int i = 0; i < nSize; i++)
pwszDst[i] = pwszDst[i + 1];
std::wstring wcharString(pwszDst);
delete pwszDst;
return wcharString;
}
std::string ws2s1( std::wstring & wstr)
{
std::string ret;
std::mbstate_t state = {};
const wchar_t *src = wstr.data();
size_t len = std::wcsrtombs(nullptr, &src, 0, &state);
if (static_cast<size_t>(-1) != len) {
std::unique_ptr< char[] > buff(new char[len + 1]);
len = std::wcsrtombs(buff.get(), &src, len, &state);
if (static_cast<size_t>(-1) != len) {
ret.assign(buff.get(), len);
}
}
return ret;
}
std::wstring s2ws1( std::string & str)
{
std::wstring ret;
std::mbstate_t state = {};
const char *src = str.data();
size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
if (static_cast<size_t>(-1) != len) {
std::unique_ptr< wchar_t[] > buff(new wchar_t[len + 1]);
len = std::mbsrtowcs(buff.get(), &src, len, &state);
if (static_cast<size_t>(-1) != len) {
ret.assign(buff.get(), len);
}
}
return ret;
}
std::string ws2s( std::wstring& src)
//std::string ws2s_conv(const std::wstring& src)
{
std::locale sys_locale("");
const wchar_t* data_from = src.c_str();
const wchar_t* data_from_end = src.c_str() + src.size();
const wchar_t* data_from_next = 0;
int wchar_size = 4;
char* data_to = new char[(src.size() + 1) * wchar_size];
char* data_to_end = data_to + (src.size() + 1) * wchar_size;
char* data_to_next = 0;
memset(data_to, 0, (src.size() + 1) * wchar_size);
typedef std::codecvt<wchar_t, char, mbstate_t> convert_facet;
mbstate_t out_state = 0;
auto result = std::use_facet<convert_facet>(sys_locale).out(
out_state, data_from, data_from_end, data_from_next,
data_to, data_to_end, data_to_next);
if (result == convert_facet::ok)
{
std::string dst = data_to;
delete[] data_to;
return dst;
}
else
{
printf("convert error!\n");
delete[] data_to;
return std::string("");
}
}
std::wstring s2ws( std::string& src)
//std::wstring s2ws_conv(const std::string& src)
{
std::locale sys_locale("");
const char* data_from = src.c_str();
const char* data_from_end = src.c_str() + src.size();
const char* data_from_next = 0;
wchar_t* data_to = new wchar_t[src.size() + 1];
wchar_t* data_to_end = data_to + src.size() + 1;
wchar_t* data_to_next = 0;
wmemset(data_to, 0, src.size() + 1);
typedef std::codecvt<wchar_t, char, mbstate_t> convert_facet;
mbstate_t in_state = 0;
auto result = std::use_facet<convert_facet>(sys_locale).in(
in_state, data_from, data_from_end, data_from_next,
data_to, data_to_end, data_to_next);
if (result == convert_facet::ok)
{
std::wstring dst = data_to;
delete[] data_to;
return dst;
}
else
{
printf("convert error!\n");
delete[] data_to;
return std::wstring(L"");
}
}
//std::string ws2s( std::wstring& src)
const std::string ws2utf8(const std::wstring& src)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
return conv.to_bytes(src);
}
//std::wstring s2ws( std::string& src)
const std::wstring utf8_2_ws(const std::string& src)
{
std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
return conv.from_bytes(src);
}
std::string ws2s_old(std::wstring& inputws){ return WChar2Ansi(inputws.c_str()); }
std::wstring s2ws_old(std::string& s){ return Ansi2WChar(s.c_str(), s.size()); }
static std::wstring string2wstring(const std::string & rString, UINT codepage)
{
int len = MultiByteToWideChar(codepage, 0, rString.c_str(), -1, NULL, 0);
if (len > 0)
{
std::vector<wchar_t> vw(len);
MultiByteToWideChar(codepage, 0, rString.c_str(), -1, &vw[0], len);
return &vw[0];
}
else
return L"";
}
static std::string wstring2string(const std::wstring & rwString, UINT codepage)
{
int len = WideCharToMultiByte(codepage, 0, rwString.c_str(), -1, NULL, 0, NULL, NULL);
if (len > 0)
{
std::vector<char> vw(len);
WideCharToMultiByte(codepage, 0, rwString.c_str(), -1, &vw[0], len, NULL, NULL);
return &vw[0];
}
else
return "";
}