某短线精灵协议的监控实现

发个前年写的短线精灵协议逆向的代码,Hook的recv函数,然后监控每个数据包结构,可以通过该方法实现所有客户端功能吧。数据包结构确实逆向花了几天时间,还是简单的。顺便入门了一下VC++,还测试了一下调用python代码,好像不能多线程调用就放弃了。写过的东西太多了,这只是个小例子。

效果的话,大概就是这样,可以加入一些股池来触发自动打板,这里触发监控条件后,通过WEB请求东方财富接口获取资金信息进行二次判断。

#include "pch.h"

#include <cstdio>
#include <ctime>
#include <iomanip>
#include <string>
#include <windows.h>
#include <iostream>
#include <winsock.h>
#include <WinInet.h>
#include <map>
#include <time.h>
#include <fstream>

#include "detours.h"
#include "configor/json.hpp"

#pragma comment(lib,"ws2_32.lib")
#pragma comment (lib, "wininet.lib")
#pragma comment (lib, "detours.lib")

using namespace std;
using namespace configor;






// 多线程参数用到的结构
struct stock_info
{
	char time[10];
	char stock[10];
	int type;
	char num[20];
};




HANDLE g_hFile;
HANDLE g_hFile2;
SYSTEMTIME systm;
map<DWORD, string> msg_type_map;
vector<string>stock_list;
string follow_type_list[] = { "大笔买入", "单笔冲涨", "急速拉升", "逼近涨停", "区间放量涨", "区间放量平","打开跌停板", "打开涨停板", "封涨停板", "涨停大减", "跌停大减", "强势封涨停" };
char g_get_host[] = { "push2.eastmoney.com" };
char g_stock_dd[] = { "/api/qt/ulist.np/get?&fltt=2&secids=%s&fields=f62,f184&_=%d" };
char g_stock_info_url[] = { "/api/qt/stock/get?&fltt=2&secid=%s&fields=f58,f168,f170&_=%d" };
size_t follow_type_size = sizeof(follow_type_list) / sizeof(follow_type_list[0]);

int (WINAPI* pRecv)(SOCKET s, char* buf, int len, int flags) = recv;
int (WINAPI* pSend)(SOCKET s, const char* buf, int len, int flags) = send;


int WINAPI MySend(SOCKET s, const char* buf, int len, int flags);
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags);
string HttpRequest(string site, string param);
void InitConsoleWindows();
void IsFileExist(const char* csFile);
void write_file(HANDLE hfile, const char* type_str, const char* time, const char* stock, const char* info);
void get_url_info(const char* stock, const char* args, string& out);
void pymain(const char* time, const char* stock, int type_id, const char* num);
DWORD WINAPI SaveStockInfoThread(LPVOID lpargs);
VOID PrintHex(PBYTE Data, ULONG dwBytes);
void DbgPrintA(LPCSTR lpszFormat, ...);
int htoi(char s[]);
char* UtfToGbk(const char* utf8);
void get_stock_info(const char* stock, int type_id, string& str_args1, float& f_args2);
void get_stock_dd(const char* stock, int type_id, float& f_args1, float& f_args2);
void write_file_close(const char* filename, const char* write_buf);
void read_stocks();
bool search_buy_stock(const char* stock);
DWORD WINAPI Mod1Thread(LPVOID lpargs);



template<typename ... Args>
static std::string str_format(const std::string& format, Args ... args)
{
	auto size_buf = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1;
	std::unique_ptr<char[]> buf(new(std::nothrow) char[size_buf]);

	if (!buf)
		return std::string("");

	std::snprintf(buf.get(), size_buf, format.c_str(), args ...);
	return std::string(buf.get(), buf.get() + size_buf - 1);
}



// 获取主力资金
void get_stock_dd(const char* stock, int type_id, float& f_args1, float& f_args2) {
	try {
		// 获取股票信息
		string out_json;
		json json_info;
		get_url_info(stock, g_stock_dd, out_json);
		json_info = json::parse(out_json.c_str());
		f_args2 = json_info["data"]["diff"][0]["f62"].get<float>();
		f_args1 = json_info["data"]["diff"][0]["f184"].get<float>();
	}
	catch (...) {
		cout << "get_stock_dd() catch (...)\r\n" << endl;
		f_args1 = 0.0;
		f_args2 = 0.0;
	}
}



// 获取股票信息
void get_stock_info(const char* stock, int type_id, string& str_args1, float& f_args2) {
	try {
		// 获取股票信息
		string out_json;
		string stock_info = "";
		json json_info;

		get_url_info(stock, g_stock_info_url, out_json);
		json_info = json::parse(out_json.c_str());
		string rname = json_info["data"]["f58"].get<string>();
		str_args1 = UtfToGbk(rname.c_str());
		f_args2 = json_info["data"]["f170"].get<float>();
	}
	catch (...) {
		cout << "get_stock_info() catch (...)\r\n" << endl;
		str_args1 = "";
		f_args2 = 0.0;
	}
}


void read_stocks() {
	// 获取股票列表
	string out_json;
	json json_stock;
	std::ifstream ifs("test.json");
	if (!ifs.is_open())
	{
		std::cout << "Open json file failed!" << std::endl;
		return;
	}

	ifs >> json_stock;
	// 使用迭代器遍历
	for (auto iter = json_stock.begin(); iter != json_stock.end(); iter++) {
		stock_list.push_back(iter.value().as_string());
		//std::cout << iter.value().as_string() << "\r\n";
	}
	return;
}



bool search_buy_stock(const char* stock) {
	if (std::find(stock_list.begin(), stock_list.end(), stock) != stock_list.end())
	{
		//cout << "存在\r\n";
		return true;
	}
	return false;

}

void my_init(const char* file_name, const char* file_name2) {
	msg_type_map[0x40080cd1] = "区间放量涨";
	msg_type_map[0x40080cd2] = "区间放量跌";
	msg_type_map[0x40080cd3] = "区间放量平";
	msg_type_map[0x40080cd4] = "单笔冲涨";
	msg_type_map[0x40080cd5] = "单笔冲跌";
	msg_type_map[0x40080cd6] = "大笔买入";
	msg_type_map[0x40080cd7] = "大笔卖出";
	msg_type_map[0x40080cd8] = "封涨停板";
	msg_type_map[0x40080cd9] = "打开涨停板";
	msg_type_map[0x40080cda] = "封跌停板";
	msg_type_map[0x40080cdb] = "打开跌停板";
	msg_type_map[0x40080cdc] = "急速拉升";
	msg_type_map[0x40080cdd] = "猛烈打压";
	msg_type_map[0x40080cde] = "涨幅超过10%的整数倍";
	msg_type_map[0x40080cdf] = "涨幅超过10%的整数倍速";
	msg_type_map[0x40080ce0] = "逼近涨停";
	msg_type_map[0x40080ce1] = "逼近跌停";
	msg_type_map[0x40080ce2] = "涨停大减";
	msg_type_map[0x40080ce3] = "跌停大减";
	msg_type_map[0x40080ce4] = "强势封涨停";
	msg_type_map[0x40080ce5] = "竞价冲涨";
	msg_type_map[0x40080ce6] = "竞价下跌";
	msg_type_map[0x40080ce7] = "买一剩余大";
	msg_type_map[0x40080ce8] = "卖一剩余大";
	msg_type_map[0x40080ce9] = "涨停试盘";
	msg_type_map[0x40080cea] = "跌停试盘";
	msg_type_map[0x40080ceb] = "竞价抢筹";
	msg_type_map[0x40080cec] = "竞价砸盘";
	msg_type_map[0x40080ced] = "竞价大买试盘";
	msg_type_map[0x40080cee] = "强势封跌停";
	msg_type_map[0x40080cef] = "急速拉升";
	msg_type_map[0x40080cf0] = "急速拉升";
	msg_type_map[0x40080cf1] = "急速拉升";
	msg_type_map[0x40080cf2] = "急速拉升";
	msg_type_map[0x40080cf3] = "急速拉升";
	msg_type_map[0x40080cf4] = "猛烈打压";
	msg_type_map[0x40080cf5] = "猛烈打压";
	msg_type_map[0x40080cf6] = "猛烈打压";
	msg_type_map[0x40080cf7] = "猛烈打压";
	msg_type_map[0x40080cf8] = "猛烈打压";
	msg_type_map[0x40080cf9] = "主力急入";
	msg_type_map[0x40080cfa] = "主力急出";
	msg_type_map[0x40080cfb] = "急速上涨";
	msg_type_map[0x40080cfc] = "猛烈下跌";

	// 2.初始化互斥量
	//InitializeCriticalSection(&g_cs);
	// 检测是否存在
	IsFileExist(file_name);
	IsFileExist(file_name2);
	// 打开文件
	g_hFile = ::CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
	if (g_hFile == INVALID_HANDLE_VALUE)
	{
		CloseHandle(g_hFile);
		return;
	}

	g_hFile2 = ::CreateFileA(file_name2, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
	if (g_hFile == INVALID_HANDLE_VALUE)
	{
		CloseHandle(g_hFile2);
		return;
	}

	
	// 读取json
	read_stocks();


	// show content:
	//for (map<DWORD, string>::iterator it = msg_type_map.begin(); it != msg_type_map.end(); ++it)
	//	cout << it->first << " => " << it->second.c_str() << '\n';

	return;
}


void get_url_info(const char* stock, const char* args, string& out) {
	string str_stock = "";
	char get_args[0x100] = { 0 };
	if ((stock[0] == '0' && stock[1] == '0') || (stock[0] == '3'))
	{
		str_stock = "0." + string(stock);
	}
	else
	{
		str_stock = "1." + string(stock);
	}
	sprintf_s(get_args, args, str_stock.c_str(), time(0));

	out = HttpRequest(g_get_host, get_args);

}


void pymain(const char* time, const char* stock, int type_id, const char* num) {

	bool need_save = false;
	string stock_info = "";
	string str_time = time;
	string str_stock = stock;
	string str_type = msg_type_map[type_id];  // 获取涨跌类型

	if (!str_type.empty())
	{
		for (size_t i = 0; i < follow_type_size; i++)
		{
			// 在关注列表中就写入到文件
			if (follow_type_list[i].compare(str_type) == 0)
			{
				need_save = true;
				break;
			}
		}

		if (need_save)
		{
			try {
				// 获取股票信息
				string out_json_zl;
				string out_json_info;
				string stock_info = "";
				json json_zl;
				json json_info3;
				get_url_info(stock, g_stock_dd, out_json_zl);
				json_zl = json::parse(out_json_zl.c_str());
				float zl_jingliuru = json_zl["data"]["diff"][0]["f62"].get<float>();
				float zl_jingbi = json_zl["data"]["diff"][0]["f184"].get<float>();

				get_url_info(stock, g_stock_info_url, out_json_info);
				json_zl = json::parse(out_json_info.c_str());
				if (json_zl["data"].empty())
				{
					stock_info = str_format("主力净流入:%.01f 主力净比:%.02f%%", zl_jingliuru, zl_jingbi);
				}
				else
				{
					string rname = json_zl["data"]["f58"].get<string>();
					string name = UtfToGbk(rname.c_str());
					float zhangdie = json_zl["data"]["f170"].get<float>();
					float huanshou = json_zl["data"]["f168"].get<float>();
					float jine = json_zl["data"]["f48"].get<float>();
					stock_info = str_format("股票:%s 换手:%.02f%% 成交金额:%.02f 主力净流入:%.01f 主力净比:%.02f%%", name.c_str(), huanshou, jine, zl_jingliuru, zl_jingbi);
				}
				write_file(g_hFile, str_type.c_str(), str_time.c_str(), str_stock.c_str(), stock_info.c_str());
			}
			catch (...) {
				cout << "catch (...)" << endl;
				write_file(g_hFile, str_type.c_str(), str_time.c_str(), str_stock.c_str(), stock_info.c_str());
			}
		}
		else {
			string stock_info = "";
			write_file(g_hFile2, str_type.c_str(), str_time.c_str(), str_stock.c_str(), stock_info.c_str());
		}
	}
}

DWORD WINAPI SaveStockInfoThread(LPVOID lpargs) {
	stock_info* p = (stock_info*)lpargs;	// 转换为结构体指针
	pymain(p->time, p->stock, p->type, p->num);
	return 0;
}






void mod1(const char* time, const char* stock, int type_id, const char* num) {
	bool need_save = false;
	string buy_msg = "";
	string str_time = time;
	string str_stock_name = "";
	string str_stock = stock;
	string str_type = msg_type_map[type_id];  // 获取涨跌类型
	float f_zhangfu = 0.0;
	float f_dd_zb = 0.0;
	float f_dd_jlr = 0.0;

	if (!str_type.empty())
	{
		for (size_t i = 0; i < follow_type_size; i++)
		{
			// 大单买入类型
			if (follow_type_list[i].compare(str_type) == 0)
			{
				// 在关注股票列表中
				need_save = search_buy_stock(stock);
				break;
			}
		}
		if (need_save)
		{
			try {
				// 获取股票名称和涨幅
				get_stock_info(stock, type_id, str_stock_name, f_zhangfu);
				if (str_stock_name.empty()) {
					get_stock_info(stock, type_id, str_stock_name, f_zhangfu);
				}
				// 涨幅>4.5%
				if (f_zhangfu >= 4.5)
				{
					get_stock_dd(stock, type_id, f_dd_zb, f_dd_jlr);
					if (f_dd_jlr == 0.0) {
						get_stock_dd(stock, type_id, f_dd_zb, f_dd_jlr);
					}
					// 大单净流入为正 占比>10%
					if (f_dd_zb > 0 && f_dd_jlr > 10)
					{
						cout << "!!!!!!!!!!!!!!!!!!\r\n";
						buy_msg = str_format("[买入下单] %s %s %s %s 涨幅:%0.2f%% 主力占比:%0.2f%% 主力净流入:%0.2f\r\n", time, stock, str_type.c_str(), str_stock_name.c_str(), f_zhangfu, f_dd_zb, f_dd_jlr);
						printf(buy_msg.c_str());
						write_file_close("买入记录.txt", buy_msg.c_str());
					}
				}
			}
			catch (...) {
				cout << "mod1 catch (...)" << endl;
			}
		}
		else {
		}
	}
}

DWORD WINAPI Mod1Thread(LPVOID lpargs) {
	cout << "Mod1Thread 运行\r\n";
	stock_info* p = (stock_info*)lpargs;	// 转换为结构体指针
	mod1(p->time, p->stock, p->type, p->num);
	return 0;
}



int WINAPI MySend(SOCKET s, const char* buf, int len, int flags)
{
	//OutputDebugStringA("MySend");
	return pSend(s, buf, len, flags);
}

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{
	stock_info S_info = { 0 };
	char sz_id[9] = { 0 };
	char sz_msg[0x100] = { 0 };
	DWORD dw_num_id = 0;
	DWORD dw_num = 0;
	HANDLE hThread = NULL;

	// 获取消息ID
	memcpy(sz_id, buf + 4, 8);
	string str_id = sz_id;

	// 存在消息ID再往下走
	if (str_id.find("0000") == str_id.npos)
	{
		return pRecv(s, buf, len, flags);
	}

	// 短线精灵消息ID
	if (str_id.compare("000000ba") == 0)
	{
		// 判断头部是否包含"market="
		lstrcpyA(sz_msg, buf + 4);
		string str_msg(sz_msg);
		if (str_msg.find("market=") == str_msg.npos)
		{
			return pRecv(s, buf, len, flags);
		}

		// 获取股票ID
		memcpy(S_info.stock, buf + 0xac, 6);
		// 获取短线精灵ID
		S_info.type = *(DWORD*)(DWORD)(buf + 0xb3);
		// 获取类型ID
		dw_num_id = *(DWORD*)(DWORD)(buf + 0xb7);
		
		// 获取当前本地系统时间 时:分:秒
		GetLocalTime(&systm);
		sprintf_s(S_info.time, "%.2d:%.2d:%.2d", systm.wHour, systm.wMinute, systm.wSecond);

		// 保存股票信息
		//hThread = CreateThread(0, 0, SaveStockInfoThread, &S_info, 0, 0);
		//if (hThread){
		//	CloseHandle(hThread);
		//}
		// 模型1
		hThread = CreateThread(0, 0, Mod1Thread, &S_info, 0, 0);
		if (hThread){
			CloseHandle(hThread);
		}

		// 打印涨跌信息
		string type_str = msg_type_map[S_info.type];  
		if (!type_str.empty())
		{
			DbgPrintA("[THS]%s %s %s", S_info.time, S_info.stock, type_str.c_str());
		}
		else {
			DbgPrintA("[THS]%s %s %x", S_info.time, S_info.stock, S_info.type);
		}
	}
	return pRecv(s, buf, len, flags);
}



extern "C" __declspec(dllexport) void dummy(void) {
	return;
}




void test() {
	stock_info S_info = { 0 };
	lstrcpyA(S_info.stock, "002629");
	lstrcpyA(S_info.time, "11:11:11");
	S_info.type = 0x40080cd6;
	Mod1Thread(&S_info);

	for (size_t i = 0; i < 5*60; i++)
	{
		HWND h_hwnd = FindWindowA(0, "同花顺(v9.10.20) - 上证指数");
		ShowWindow(h_hwnd, SW_HIDE);
		Sleep(200);
	}
	system("taskkill /IM xiadan.exe");
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
	if (DetourIsHelperProcess()) {
		return TRUE;
	}
	if (dwReason == DLL_PROCESS_ATTACH) {

		my_init("热点.txt", "冰点.txt");
		InitConsoleWindows();
		CreateThread(0,0,(LPTHREAD_START_ROUTINE)test, 0, 0, 0);


		DetourRestoreAfterWith();

		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)pSend, MySend);
		DetourTransactionCommit();


		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)pRecv, MyRecv);
		DetourTransactionCommit();
	}
	else if (dwReason == DLL_PROCESS_DETACH) {
		CloseHandle(g_hFile);
		CloseHandle(g_hFile2);
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourDetach(&(PVOID&)pSend, MySend);
		DetourTransactionCommit();

		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourDetach(&(PVOID&)pRecv, MyRecv);
		DetourTransactionCommit();
	}
	return TRUE;
}






void InitConsoleWindows()
{
	AllocConsole();

#if _MSC_VER <= 1200 //这个是vc6.0
	freopen("CONOUT$", "w+t", stdout);
#else //这个是vc2003以上
	FILE* stream;
	freopen_s(&stream, "CONOUT$", "wt", stdout);
	freopen_s(&stream, "CONIN", "rt", stdin);

#endif
}




string HttpRequest(string site, string param) {
	HINTERNET hInternet = InternetOpenW(L"YourUserAgent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); //you should perhaps edit your useragent ? :p
	if (hInternet == NULL) {
		return "InternetOpenW failed(hInternet): " + GetLastError();
	}
	else {
		wstring widestr;
		for (size_t i = 0; i < site.length(); ++i) {
			widestr += wchar_t(site[i]);
		}
		const wchar_t* site_name = widestr.c_str();
		wstring widestr2;
		for (size_t i = 0; i < param.length(); ++i) {
			widestr2 += wchar_t(param[i]);
		}
		const wchar_t* site_param = widestr2.c_str();
		// We need to convert str to const wchar_t as the args require!
		HINTERNET hConnect = InternetConnectW(hInternet, site_name, 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);
		if (hConnect == NULL) {
			return "InternetConnectW failed(hConnect == NULL): " + GetLastError();
		}
		else {
			const wchar_t* parrAcceptTypes[] = { L"text/*", NULL }; // accepted types. We'll choose text.
			HINTERNET hRequest = HttpOpenRequestW(hConnect, L"GET", site_param, NULL, NULL, parrAcceptTypes, 0, 0);
			if (hRequest == NULL) {
				return "HttpOpenRequestW failed(hRequest == NULL): " + GetLastError();
			}
			else {
				BOOL bRequestSent = HttpSendRequestW(hRequest, NULL, 0, NULL, 0);
				if (!bRequestSent) {
					return "!bRequestSent    HttpSendRequestW failed with error code " + GetLastError();
				}
				else {
					std::string strResponse;
					const int nBuffSize = 1024;
					char buff[nBuffSize];
					BOOL bKeepReading = true;
					DWORD dwBytesRead = -1;
					while (bKeepReading && dwBytesRead != 0) {
						bKeepReading = InternetReadFile(hRequest, buff, nBuffSize, &dwBytesRead);
						strResponse.append(buff, dwBytesRead);
					}
					return strResponse;
				}
				InternetCloseHandle(hRequest);
			}
			InternetCloseHandle(hConnect);
		}
		InternetCloseHandle(hInternet);
	}
}




void IsFileExist(const char* csFile)
{
	DWORD dwAttrib = GetFileAttributesA(csFile);
	if (INVALID_FILE_ATTRIBUTES == dwAttrib) {
		HANDLE hFile = ::CreateFileA(csFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
		CloseHandle(hFile);
	}
}


char* UtfToGbk(const char* utf8)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
	len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}



void write_file(HANDLE hfile, const char* type_str, const char* time, const char* stock, const char* info) {

	char szbuf[0x200] = { 0 };

	sprintf_s(szbuf, "%s %s %s %s\r\n", time, stock, type_str, info);

	//写数据
	DWORD writesize = 0;
	//设置偏移量 到文件尾部 配合OPEN_EXISTING使用 可实现追加写入文件
	SetFilePointer(hfile, NULL, NULL, FILE_END);
	WriteFile(hfile, szbuf, strlen(szbuf), &writesize, NULL);
	//刷新文件缓冲区
	FlushFileBuffers(hfile);
	//CloseHandle(g_hFile);

	return;
}


void write_file_close(const char* filename, const char* write_buf) {
	// 检测是否存在
	IsFileExist(filename);
	// 打开文件
	HANDLE hFile = ::CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		CloseHandle(hFile);
		return;
	}
	//写数据
	DWORD writesize = 0;
	//设置偏移量 到文件尾部 配合OPEN_EXISTING使用 可实现追加写入文件
	SetFilePointer(hFile, NULL, NULL, FILE_END);
	WriteFile(hFile, write_buf, strlen(write_buf), &writesize, NULL);
	//刷新文件缓冲区
	FlushFileBuffers(hFile);
	CloseHandle(hFile);
	return;
}







VOID PrintHex(PBYTE Data, ULONG dwBytes) {
	printf("\r\n");
	for (ULONG i = 0; i < dwBytes; i += 16) {
		printf("%.8x: ", i);

		for (ULONG j = 0; j < 16; j++) {
			if (i + j < dwBytes) {
				printf("%.2x ", Data[i + j]);
			}
			else {
				printf("?? ");
			}
		}

		for (ULONG j = 0; j < 16; j++) {
			if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
				printf("%c", Data[i + j]);
			}
			else {
				printf(".");
			}
		}

		printf("\n");
	}
}

void DbgPrintA(LPCSTR lpszFormat, ...)
{
	va_list   args;
	CHAR     szBuffer[0x1000];
	va_start(args, lpszFormat);
	wvsprintfA(szBuffer, lpszFormat, args);
	OutputDebugStringA(szBuffer);
	printf(szBuffer);
	printf("\r\n");
	va_end(args);

}




//将十六进制的字符串转换成整数  
int htoi(char s[])
{
	int i;
	int n = 0;
	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
	{
		i = 2;
	}
	else
	{
		i = 0;
	}
	for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'); ++i)
	{
		if (tolower(s[i]) > '9')
		{
			n = 16 * n + (10 + tolower(s[i]) - 'a');
		}
		else
		{
			n = 16 * n + (tolower(s[i]) - '0');
		}
	}
	return n;
}





发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注