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

最新文章

  1. Android Drawable
  2. Mathout
  3. PAT乙级 1027. 打印沙漏(20)
  4. 共享内存 最快IPC 的原因
  5. Java 中无参无返回值方法的使用
  6. 【学习总结】iOS 数据保存几种方式总结
  7. c++ string assign =
  8. 解决DropDownList 有一个无效 SelectedValue,因为它不在项目列表中。这是怎么回事?
  9. MySQL的EXPLAIN命令详解(转)
  10. 在Eclipse的DDMS中查看手机data文件夹中的内容
  11. commons-logging 和 log4j 之间的关系
  12. tweenanim动画
  13. TTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
  14. TensorFlow anaconda命令备忘
  15. [算法题] Reverse Linked List
  16. EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)
  17. TCP三次握手及TCP连接状态 TCP报文首部格式
  18. 【做题】POI2011R1 - Plot——最小圆覆盖&amp;倍增
  19. Condtion type Z123 is mandatory!
  20. Mysql --初识mysql语句

热门文章

  1. Archlinux系统运维
  2. SVN图标含义说明
  3. scrollIntoView 前的元素滚动到浏览器窗口的可视区域内 不止垂直滚动,还有水平滚动
  4. Linux下运行命令出现is not in the sudoers file的问题
  5. Redis:slave flush old data造成实例不可用
  6. Angular总结
  7. JMeter接口测试-计数器
  8. jenkins-设置定时任务
  9. Docker实战之Kafka集群
  10. mysql中用SQL增加、删除字段,修改字段名