ip-guard网络通信加解密

ip-guard官网:https://www.e-dlp.com/tuzhijiamixitong/index.html?msclkid=e207d5eb8fe21d7b6d80bfe10f1c416d&utm_source=bing&utm_medium=cpc&utm_campaign=%E7%AB%9E%E5%93%81001&utm_term=IP-guard&utm_content=%E5%93%81%E7%89%8C%E8%AF%8D%E8%AE%A1%E5%88%92

主要基于des和aes-cbc-128算法。主要的坑:

  1. aes解密后头部16字节完全无用被丢弃。
  2. deflate解压。从头部2字节0x7801看出,压缩时的参数为速度最快算法。
  3. des密钥"ocularv3"
  4. aes密钥为: des解密后的包头第8字节开始的16字节,iv为16字节的0串。cbc算法会根据aes解密结果更新iv,所以iv会发生变化、但是无需干涉。

废话不说,上干货。

代码使用openssl库中的evp接口解密。

cpp 复制代码
int __stdcall TcpClient(string ip,int port) {

	int ret = 0;

	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (s == INVALID_SOCKET) {
		perror("socket\r\n");
		return -1;
	}

	sockaddr_in sa = { 0 };
	sa.sin_family = AF_INET;
	sa.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
	sa.sin_port = ntohs(port);

	ret = connect(s, (sockaddr*)&sa, sizeof(sockaddr_in));
	if (ret < 0) {
		perror("connect\r\n");
		return -1;
	}
	int bufsize = 0x1000000;
	char* sendbuf = new char[bufsize];

	char* recvbuf= new char[bufsize];

	DES_key_schedule key_schedule;
	DES_cblock deskey;

	memcpy((char*)deskey, "ocularv3", 8);
	DES_set_key_unchecked(&deskey, &key_schedule);

	unsigned char decryptbuf[0x1000] = { 0 };

	unsigned char encryptbuf[0x1000] = { 0 };

	int recvLen = 0;

	char packetbuf[0x1000];
	int packlen = makeFakePacket(packetbuf);

	DWORD zipsize = packlen * 16;
	unsigned char* zipbuf = new unsigned char[packlen + 1024];
	ret=zcompress((Bytef*)packetbuf, packlen, zipbuf, (uLong*)&zipsize);

	memcpy((Bytef*)sendbuf + 16 + sizeof(OCP_HEADER), zipbuf, zipsize);

	int sendsize = zipsize+16;
	
	OCP_HEADER* hdr = (OCP_HEADER*)sendbuf;

	memset(hdr, 0, sizeof(OCP_HEADER));
	for (int i = 0; i < 16; i++) {
		sendbuf[8 + i] = 'A';
	}
	for (int i = 0; i < 16; i++) {
		sendbuf[32 + i] = 'B';
	}
	hdr->tag = 0x4d4f;
	hdr->payloadLen = sendsize;
	hdr->flag = 0x4000|0x8000;
	hdr->cmd = 0xc600;
	
	const char* key = "ocularv3";
	
	unsigned char iv[16] = { 0 };
	char* indata = 0; 
	char* outdata = 0;

	AESCBC128Encryptor aes_enc((unsigned char*)&hdr->field8, iv);
	unsigned char aes_enc_buf[0x1000];
	int aes_enc_len = aes_enc.update((unsigned char*)sendbuf + sizeof(OCP_HEADER), hdr->payloadLen, aes_enc_buf);
	int aes_enc_last_len = aes_enc.final((unsigned char*)aes_enc_buf + aes_enc_len);
	memcpy(sendbuf + sizeof(OCP_HEADER), aes_enc_buf, aes_enc_last_len + aes_enc_len);

	sendsize = aes_enc_last_len + aes_enc_len;
	hdr->payloadLen = aes_enc_last_len + aes_enc_len;

	indata = (char*)&hdr->field8;
	outdata = (char*)encryptbuf;
	for (int i = 0; i < 3; i++) {
		DES_ecb_encrypt((const_DES_cblock*)indata,
			(DES_cblock*)outdata,
			&key_schedule,
			DES_ENCRYPT);
		indata += 8;
		outdata += 8;
	}

	memcpy((char*) & hdr->field8, encryptbuf, 24);

	indata = (char*)encryptbuf;
	outdata = (char*)decryptbuf;
	for (int i = 0; i < 4; i++) {
		DES_ecb_encrypt((const_DES_cblock*)indata,
			(DES_cblock*)outdata,
			&key_schedule,
			DES_DECRYPT);
		indata += 8;
		outdata += 8;
	}
	AESCBC128Decryptor aes_dec((unsigned char*)decryptbuf, iv);
	unsigned char aes_dec_buf[0x1000];
	int aes_dec_len = aes_dec.update((unsigned char*)sendbuf + sizeof(OCP_HEADER), sendsize, aes_dec_buf);
	int aes_dec_last_len = aes_dec.final((unsigned char*)aes_dec_buf + aes_dec_len);

	ret = send(s, (char*)sendbuf, sendsize+sizeof(OCP_HEADER), 0);
	
	recvLen = recv(s, recvbuf, bufsize-1, 0);
	if (recvLen > 0 && recvLen < bufsize) {
		recvbuf[recvLen] = 0;

		int procLen = 0;
		char* procBuf = recvbuf;
		unsigned char* dstbuf = decryptbuf;
		while(procLen < recvLen){
			OCP_HEADER* hdr = (OCP_HEADER*)(procBuf);
			if (hdr->flag & 0x4100) {
				char* indata = (char*)&hdr->field8;
				char* outdata = (char*)dstbuf + 8;
				memcpy(dstbuf, procBuf, 8);
				for (int i = 0; i < 3; i++) {
					DES_ecb_encrypt((const_DES_cblock*)indata,
						(DES_cblock*)outdata,
						&key_schedule,
						DES_DECRYPT);
					indata += 8;
					outdata += 8;
				}

				hdr = (OCP_HEADER*)dstbuf;
				if (hdr->payloadLen) {
					AESCBC128Decryptor aes_dec((unsigned char*)dstbuf + 8, iv);
					unsigned char aes_dec_buf[0x1000];
					int aes_dec_len = aes_dec.update((unsigned char*)procBuf + sizeof(OCP_HEADER), hdr->payloadLen, aes_dec_buf);
					int aes_last_dec_len = aes_dec.final((unsigned char*)aes_dec_buf + aes_dec_len);

					procLen += hdr->payloadLen;
				}
				procLen += sizeof(OCP_HEADER);
				procBuf += procLen;
				dstbuf += procLen;
			}
		}
	}
	
	closesocket(s);

	delete [] sendbuf;

	delete[] recvbuf;
	
	return 0;
}
相关推荐
IpdataCloud6 小时前
如何用Python和IP离线库查询IP归属地?获取国家、城市、经纬度的完整代码
开发语言·python·tcp/ip
meilindehuzi_a6 小时前
【Linux 进程基础】一文读懂命令行参数与环境变量
linux·服务器
用户86859214418746 小时前
Linux I2C 调试实录:用寄存器打印揪出 TRISE 配置过小
linux
脆皮炸鸡7556 小时前
进程信号~信号的产生
linux·服务器·开发语言·经验分享·笔记·学习方法
Emtronix英创6 小时前
RK3568 CAN驱动测试及使用说明
linux·arm开发·rk3568·全国产主板
vortex56 小时前
CentOS 系包管理器完全指南:从 dnf 到 rpm
linux·运维·centos
SZ放sai哑滋7 小时前
工控机刷Linux、Qt教程
linux·运维·服务器
MY_TEUCK7 小时前
【2026最新Linux本地部署Ollama】Ollama Linux 安装全流程(含离线 / 开机自启 / 远程访问)
linux·运维·服务器
cd_949217217 小时前
星思半导体:深耕芯片研发,助力卫星互联网产业高质量发展
网络·人工智能