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;
}
相关推荐
AlfredZhao1 天前
生产环境里,为什么不建议把普通端口直接暴露到公网?
linux·https·443·80
MrSYJ1 天前
TCP协议理解
后端·tcp/ip
戴为沐2 天前
Linux内存扩容指南
linux
zylyehuo3 天前
Linux 彻底且安全地删除文件
linux
用户805533698033 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297913 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
Web3探索者5 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
zylyehuo5 天前
Linux系统中网线与USB网络共享冲突
linux
Sokach10156 天前
Linux Shell 脚本从零到能用:一个新手的一天学习总结
linux
AlfredZhao7 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone