记一次:Windows的Socket编程学习和分析过程
Socket编程依赖于:WS2_32.dll

--- 服务端 --- 、导入我们需要的函数
#incldue <windows.h> //#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib") 、初始化(指定要使用的socket版本)
WSADATA ws = {};
/*WSAStartup 微软MSDN:https://docs.microsoft.com/en-us/previous-versions/aa921082(v=msdn.10)?redirectedfrom=MSDN
参数1:版本号 调用者可以使用的Windows套接字最高支持。高位字节指定次要版本号(修订)。低位字节指定主要版本号。
参数2:存储socket相关的信息
返回值;成功返回0/
WSAStartuo(MAKEWORD(2,2),&ws); //MAKEWORD 是一个宏用于将其拆成2个word ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8)) 3、创建socket
/*socket 微软msdn:https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket 参数1:地址簇类型,ip地址类型
参数2:socket的类型,数据是以何种方式传输
参数3:协议类型
返回值:成功返回新的socket,失败返回INVALID_SOCKET*/ SOCKET sk = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 、设置协议地址族信息(要连接或绑定的ip端口信息)
微软MSDN:https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-sockaddr_in
SOCKADDR_IN sever_addr = {};
sever_addr.sin_family = AF_INET; //地址族类型
sever_addr.sin_port = htons(); //端口
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //地址 htons函数:intel cpu存储数据的方式采用的是:Littke-endian方式(高位在右,低位在左),而例如ibm早期cpu采用的则是:Big-endian(高位在左,低位在右),而网络协议一致采取Big-endian的方式存储数据,而htons就是将Littke转化为Big的函数
inet_addr函数:将字符串地址转化为某一种数字格式
inet_ntoa函数:将数字格式的地址转化为字符串
需要注意的是描述地址族(莫名其妙的概念)信息本应使用大小为16字节的sockaddr结构体,但是因为该结构体除了sin.family,其余全是存储在一个数组中的,这样赋值难免麻烦,所以才有了SOCKADDR_IN sockaddr:
struct sockaddr {
u_short sa_family;
char sa_data[];}; SOCKADDR_IN:
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[];
}; 、绑定(将scocket与地址族联起来
/*bind
参数1:未绑定的socket
参数2:地址族信息地址
参数3:地址族信息的大小
返回值:成功返回0,失败返回SOCKET_ERROR*/
bind(sk,(sockaddr*)&server_addr,sizeof(sockaddr)) 、监听
/*listen
参数1:已绑定未监听的socket
参数2:等待连接的队伍最大长度 SOMAXCONN表示自动设置合理值
返回值:失败返回SOCKET_ERROR,成功返回0*/
listen(sk,SOMAXCONN); 、接收连接(等待连接)
/*接收连接:accetp
参数1:已监听的socket
参数2 out :建立连接的客户端信息
参数3:传递时包含参数2的大小,返回时包含返回地址的实际长度
返回值:成功就返回已连接的套接字,否则返回INVALID_SOCKET失败信息*/
SOCKADDR_IN cline_addr = {};
DWORD len = sizeof(SOCKADDR_IN);
SOCKET _cline_socket = accetp(sk,(sockaddr*)&cline_addr,(int*)&len); accetp函数:这是一个阻塞函数,在有连接前就会等待于此 、通信
微软MSDN:https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv /*通信recv(接收) send(发送)
参数1;建立连接的socket
参数2: 接数或发送数据的缓冲区
参数3: 缓冲区长度
参数4: 发送或接数数据的方式
返回值:成功返回接数或返回的字节大小,连接正常断开返回0,其他情况返回相应的错误代码*/
char recvbuff[] = {};
while(true)
{
memset(recvbuff,,);
DWORD recvlen = recv(_cline_socket,recvbuff,,); //默认为0表示全接收,并结束函数
if(recvlen > )
{
printf("%s\r\n",recvlen);
}else
{
switch(recvlen)
{
case :
closesocket(_cline_socket); //关闭socket连接
break;
}
}
}
WSACleanup(); //释放ws2_32.dll --- 客户端 ---
客户端相较于服务端,只需要连接即可进行通信 、导入需要的函数 #incldue <windows.h> //#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib") 、创建scoket SOCKET sk = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 、创建地址族描述信息
SOCKADDR_IN sever_addr = {};
sever_addr.sin_family = AF_INET; //地址族类型
sever_addr.sin_port = htons(); //端口
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //地址 、连接到服务端 /*connect
参数1:未连接的socket
参数2:连接的议地址族信息(连接的服务端信息)
参数3:参数2的长度
返回值:成功返回0,否则返回SOCKET_ERROR*/
connect(sk,(sockadd*)&server_addr,sizeof(SOCKADDR_IN)); 、通信
char sendbuff[] = "Hello.";
DWORD Num = send(sk,sendbuff,,); ////如果返回值小于len参数,但是这是一个非阻塞套接字就表示没有发生错误
if(NUm == SOCKET_ERR)
{
printf("%s\r\n",“连接断开”);
closesocket(sk);
WSACleeanup();
}
软件界面:

根据分析找到了其回调函数:并得到其处理过程函数:
.text:004010F9 cmp [ebp+arg_4], 111h ; 判断是否是WM_COMMADN消息
.text: jnz short loc_40116E
.text: mov ecx, [ebp+arg_8]
.text: and ecx, 0FFFFh ; 获取wparam参数的低4位,也就是控件id
.text:0040110B mov [ebp+var_8], ecx
.text:0040110E mov edx, [ebp+arg_C]
.text: mov [ebp+hWnd], edx
.text: cmp [ebp+var_8], 3EAh ; 判断是否登录按钮
.text:0040111B jnz short loc_40116E
.text:0040111D mov esi, esp
.text:0040111F push ; bEnable
.text: mov eax, [ebp+hWnd]
.text: push eax ; hWnd
.text: call ds:EnableWindow
.text:0040112B cmp esi, esp
.text:0040112D call __chkesp
.text: call sub_40100F ; 处理函数
.text: test eax, eax
.text: jz short loc_401159
.text:0040113B xor ecx, ecx
.text:0040113D mov cl, byte_41AEB0
.text: cmp ecx, 77h
.text: jz short loc_401159 ; 返回值为0就重新恢复button,否则就退出程序
.text: mov esi, esp
.text:0040114A push ; uExitCode
.text:0040114C call ds:ExitProcess
sub_40100F函数内核心代码如下:将计算的随机数和用户名长度,密码长度按每个1字节写入到[ebp-0x348]这块内存,之后将用户名和密码也复制到这一块内存
0129751D |. 6A push 0x0
0129751F |. E8 7CFEFFFF call crackmen.timet_stdio_output::positiona>; 获取时间戳
|. 83C4 add esp,0x4
|. push eax
|. E8 D6B5FFFF call crackmen.01292B03
0129752D |. 83C4 add esp,0x4
|. E8 E8A0FFFF call crackmen.0129161D ; 获取随机数
|. FF000080 and eax,0x800000FF
0129753A |. jns short crackmen.
0129753C |. dec eax
0129753D |. 0D 00FFFFFF or eax,-0x100
|. inc eax
|> A7FCFFFF mov byte ptr ss:[ebp-0x359],al ; 把随机数给0x359
|. BA mov edx,0x1
0129754E |. 6BC2 imul eax,edx,0x0
|. 8A8D B0FCFFFF mov cl,byte ptr ss:[ebp-0x350]
|. 888C05 B8FCFF>mov byte ptr ss:[ebp+eax-0x348],cl ; 用户名的长度给0x348
0129755E |. BA mov edx,0x1
|. c1e2 shl edx,0x0
|. 8A85 ACFCFFFF mov al,byte ptr ss:[ebp-0x354]
0129756C |. B8FCFF>mov byte ptr ss:[ebp+edx-0x348],al ; 把密码给长度给0x348+0x1
|. B9 mov ecx,0x1
|. D1E1 shl ecx,
0129757A |. 8A95 A7FCFFFF mov dl,byte ptr ss:[ebp-0x359]
|. 88940D B8FCFF>mov byte ptr ss:[ebp+ecx-0x348],dl ; 把随机数给0x348+0x2
|. 8B85 B0FCFFFF mov eax,[local.]
0129758D |. push eax
0129758E |. 8D4D C0 lea ecx,[local.]
|. push ecx
|. 8D95 BBFCFFFF lea edx,dword ptr ss:[ebp-0x345]
|. push edx
|. E8 0DBDFFFF call crackmen.012932AB ; 将用户名复制到 [ebp-0x345]
0129759E |. 83C4 0C add esp,0xC
012975A1 |. 8B85 ACFCFFFF mov eax,[local.]
012975A7 |. push eax
012975A8 |. 8D4D lea ecx,[local.]
012975AB |. push ecx
012975AC |. 8B95 B0FCFFFF mov edx,[local.]
012975B2 |. 8D8415 BBFCFF>lea eax,dword ptr ss:[ebp+edx-0x345]
012975B9 |. push eax
012975BA |. E8 ECBCFFFF call crackmen.012932AB ; 将密码复制到 [ebp+用户名长度-0x345]
当上面步骤执行完后:从[ebp-0x348]这一块内存,就存储了如下格式的数据:04 03 77 61 61 61 61 66 66 66 前3个字节分别是:随机数,用户名长度,密码长度,后面的就是用户名和密码
对[ebp-0x348]进行简单的加密
012975C2 |. 8B8D ACFCFFFF mov ecx,[local.] ;获取用户名长度
012975C8 |. 8B95 B0FCFFFF mov edx,[local.] ;//获取密码长度
012975CE |. 8D440A lea eax,dword ptr ds:[edx+ecx+0x3] //得到整个[ebp-0x348]内存的长度
012975D2 |. A8FCFFFF mov [local.],eax ; liack0x214存储的就是整个用户名长度+整个密码长度+0x3(随机数,用户名长度值,密码长度值+)
012975D8 |. C785 9CFCFFFF>mov [local.],0x0 ; 217作为循环变量使用i
012975E2 |. EB 0F jmp short crackmen.012975F3
012975E4 |> 8B8D 9CFCFFFF /mov ecx,[local.]
012975EA |. 83C1 |add ecx,0x1 ;i++
012975ED |. 898D 9CFCFFFF |mov [local.],ecx
012975F3 |> 8B95 9CFCFFFF mov edx,[local.]
012975F9 |. 3B95 A8FCFFFF |cmp edx,[local.] ; 如果i大于等于214([ebp-0x348]缓冲区的总长度)就跳出循环
012975FF |. 7D |jge short crackmen.
|. 8B85 9CFCFFFF |mov eax,[local.]
|. 0FBE8C05 B8FC>|movsx ecx,byte ptr ss:[ebp+eax-0x348] ; 取1字节进行加密
0129760F |. 81F1 A6000000 |xor ecx,0xA6 ;
|. 8B95 9CFCFFFF |mov edx,[local.]
0129761B |. 888C15 B8FCFF>|mov byte ptr ss:[ebp+edx-0x348],cl ; 将加密后的值写回
|.^ EB C0 \jmp short crackmen.012975E4
发送数据到服务端:
|> \6A push 0x0 ; /Flags =
|. 8B85 A8FCFFFF mov eax,[local.] ; |
0129762C |. push eax ; |DataSize = A (.)
0129762D |. 8D8D B8FCFFFF lea ecx,[local.] ; |
|. push ecx ; |Data =
|. 8B95 80FCFFFF mov edx,[local.] ; |
0129763A |. push edx ; |Socket = 0x4
0129763B |. E8 call crackmen.tring_output_adapter<char> ><>; \send
接收服务端返回的数据,并进行解密:
|. 6A push 0x0 ; /Flags =
|. F4010000 push 0x1F4 ; |BufSize = 1F4 (.)
0129765B 8D85 88FDFFFF lea eax,dword ptr ss:[ebp-0x278] ; [ebp-0x278]作为接收数据的缓冲区
|. push eax ; |Buffer = 0000000A
|. 8B8D 80FCFFFF mov ecx,[local.] ; |
|. push ecx ; |Socket = 0x3
|. E8 call crackmen.<char,__crt_stdio_output::str>; \recv
0129766E |. A0FCFFFF mov [local.],eax ; 局部变量:loacal.216是接收的数据长度
|. C785 9CFCFFFF>mov [local.],0x0 ; 217作为循环值i
0129767E |. EB 0F jmp short crackmen.0129768F ;循环开始
|> 8B95 9CFCFFFF /mov edx,[local.]
|. 83C2 |add edx,0x1 ;i++
|. 9CFCFFFF |mov [local.],edx
0129768F |> 8B85 9CFCFFFF mov eax,[local.]
|. 3B85 A0FCFFFF |cmp eax,[local.] ; i < revc()
0129769B |. 7D 1F |jge short crackmen.012976BC
0129769D |. 8B8D 9CFCFFFF |mov ecx,[local.]
012976A3 |. 0FB6940D 88FD>|movzx edx,byte ptr ss:[ebp+ecx-0x278] ; 从[ebp-278]取一个字节,并解密
012976AB |. 83F2 6E |xor edx,0x6E ; 解密
012976AE |. 8B85 9CFCFFFF |mov eax,[local.]
012976B4 |. F0AE3501 |mov byte ptr ds:[eax+eeam_output_adapter<w>; 0x135AEF0 存储解密的数据内存地址0x135AEF0
012976BA |.^ EB C4 \jmp short crackmen.
根据解密后的数据进行验证:
012976BC |> \B9 mov ecx,0x1
012976C1 |. C1E1 shl ecx,0x2 ; ecx = 0x4
012976C4 |. 0FB691 F0AE35>movzx edx,byte ptr ds:[ecx+eeam_output_adap>; 从解密的数据中+0x4 取1byte 是否为0xd5
012976CB |. 81FA D5000000 cmp edx,0xD5
012976D1 |. 0F85 9E000000 jnz crackmen.01297775 ;1297775结束位置
012976D7 |. B8 mov eax,0x1
012976DC |. 6BC8 0E imul ecx,eax,0xE
012976DF |. 0FB691 F0AE35>movzx edx,byte ptr ds:[ecx+eeam_output_adap>; 从解密的数据中+0xe 取1byte
012976E6 |. 0FB685 A7FCFF>movzx eax,byte ptr ss:[ebp-0x359] ; 取之前获取的随机数
012976ED |. 3BD0 cmp edx,eax ; 判断是否合之前的获取的随机数相等
012976EF |. 0F85 jnz crackmen.
012976F5 |. B9 mov ecx,0x1
012976FA |. 6BD1 0A imul edx,ecx,0xA
012976FD |. 0FB682 F0AE35>movzx eax,byte ptr ds:[edx+eeam_output_adap>; 从解密的数据中+0xA 取1byte并+0x3,判断结果是否为0x16
|. 83C0 add eax,0x3 ; +=
|. 83F8 cmp eax,0x16 ; 判断是否为0x16
0129770A |. jnz short crackmen.
0129770C |. B9 mov ecx,0x1
|. 6BD1 imul edx,ecx,0x23 ; 从解密的数据中+0x23 取1byte 是否为0bd
|. 0FB682 F0AE35>movzx eax,byte ptr ds:[edx+eeam_output_adap>
0129771B |. 3D BD000000 cmp eax,0xBD
|. jnz short crackmen.
|. B9 mov ecx,0x1
|. 6BD1 3C imul edx,ecx,0x3C
0129772A |. 0FB682 F0AE35>movzx eax,byte ptr ds:[edx+eeam_output_adap>; 从解密的数据中+0x3c 取1byte 是否为0x43
|. 83F8 cmp eax,0x43
|. 3F jnz short crackmen.
|. B9 mov ecx,0x1
0129773B |. 6BD1 imul edx,ecx,0x42
0129773E |. 0FB682 F0AE35>movzx eax,byte ptr ds:[edx+eeam_output_adap>; 从解密的数据中+0x42 取1byte 是否为0xc6
|. 3D C6000000 cmp eax,0xC6
0129774A |. jnz short crackmen.
0129774C |. 8BF4 mov esi,esp
0129774E |. 6A push 0x0 ; /Style = MB_OK|MB_APPLMODAL
|. 58A03501 push crackmen.0135A058 ; |Title = "Crackne net-2"
|. 68A03501 push crackmen.0135A068 ; |Text = "Registration successful !"
0129775A |. 8B0D 80C63501 mov ecx,dword ptr ds:[0xnions'::`2'::_Optio>; |
|. push ecx ; |hOwner =
|. FF15 D0D13501 call dword ptr ds:[<&USER32.MessageBoxA>] ; \MessageBoxA
记一次:Windows的Socket编程学习和分析过程的更多相关文章
- socket编程学习step1
socket学习参考链接,赞一个:http://blog.csdn.net/hguisu/article/details/7445768 sockets(套接字)编程有三种,流式套接字(SOCK_ST ...
- [补] windows C socket编程——大物实验预约
注 : 心血来潮,想着把这两年没能记录下来的经历,写一波回忆杀.诚然,有些经历十分复杂繁琐,希望能耐下性子,写出好文章来,可惜一时不能全想起来这两年来的种种,就想起来什么便写什么吧. 时间估摸着是大一 ...
- JAVA Socket 编程学习笔记(二)
在上一篇中,使用了 java Socket+Tcp/IP 协议来实现应用程序或客户端--服务器间的实时双向通信,本篇中,将使用 UDP 协议来实现 Socket 的通信. 1. 关于UDP UDP协 ...
- JAVA Socket 编程学习笔记(一)
1. Socket 通信简介及模型 Java Socket 可实现客户端--服务器间的双向实时通信.java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的cli ...
- Socket编程学习之道:揭开Socket编程的面纱
对TCP/IP.UDP.Socket编程这些词你不会非常陌生吧?随着网络技术的发展.这些词充斥着我们的耳朵. 那么我想问: 1. 什么是TCP/IP.UDP? 2. S ...
- LInux下socket编程学习笔记
1.socket套接字: socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模 ...
- socket编程头文件分析
在socket网络编程中经常用到一些宏定义.结构和函数,这些经常包含在相关的头文件中,使用时直接include相关头文件即可.下面简单描述下相关的一些结构及头文件. 1. sockaddr / bi ...
- Android Socket编程学习笔记
http://blog.csdn.net/eyu8874521/article/details/8847173 度娘给出的描述:通常也称作"套接字",用于描述IP地址和端口,是一个 ...
- windows下socket编程:区分shutdown()及closesocket()
以下描述主要是针对windows平台下的TCP socket而言. 首先需要区分一下关闭socket和关闭TCP连接的区别,关闭TCP连接是指TCP协议层的东西,就是两个TCP端之间交换了一些协议包( ...
随机推荐
- Nginx 原理和架构
Nginx 是一个免费的,开源的,高性能的 HTTP 服务器和反向代理,以及 IMAP / POP3 代理服务器.Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名Nginx 里 ...
- 网络编程OSI介绍
网络编程 软件开发架构 c/s架构(client/server) c:客户端 s:服务端 客户端和服务器端架构,这种架构是从用户层划分的,一般客户端就是在用户电脑上安装的应用程序,而服务端就是公司里的 ...
- Cobalt Strike学习笔记
Cobalt Strike 一款以metasploit为基础的GUI的框架式渗透测试工具,集成了端口转发.服务扫描,自动化溢出,多模式端口监听,win exe木马生成,win dll木马生成,java ...
- 将Hexo网站托管到Coding.net
只需要注册coding.net,然后建立一个名为用户名+coding.me的仓库即可,需要注意的是 coding.net的pages仓库只能有一个master分支 开始使用 Coding Pages官 ...
- 前进中的人工智能——聚焦Faculty Summit 2015人工智能主题研讨会
Summit 2015人工智能主题研讨会" title="前进中的人工智能--聚焦Faculty Summit 2015人工智能主题研讨会"> 在近几年上映的科幻大 ...
- 网购分期不还 N种恶果等着你
N种恶果等着你" title="网购分期不还 N种恶果等着你"> 网购市场狂飙突进的发展,让每个人都享受到随时随地购物的乐趣,也在很大程度上推动商品之间的流通.目前 ...
- 会编程的 AI + 会修 Bug 的 AI,等于什么 ?
2017-02-25 Python开发者 (点击上方公众号,可快速关注) 关于人工智能未来的畅想,除了家庭服务机器人,快递无人机,医用机器人等等,Lucas Carlson 认为人工智能在另外一个领域 ...
- Welcome to Giyber Blog - LC的博客
"You can be the best! " 一切才刚开始 "不知道行不行,试试吧."抱着这样的理由,一个小白的成长记录,由此开始. 在 Mr.锤 的&quo ...
- C++扬帆远航——12(抓小偷)
/* * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:zhaoxiaotou.cpp * 作者:常轩 * 微信公众号: ...
- 【Art】物理课题——虹吸
前言(无关闲话):在此之前,课题小组讨论了三.四次,得有10个小时了总共,但是具体还是在普及常识,那就在这里深入地讲一下. 进入正题—— 这就是虹吸的基本模型,再看一下百度的官方说法: “虹吸(sip ...