从字节缓冲区中提取 IP

发布于 2024-10-15 17:35:20 字数 270 浏览 1 评论 0原文

如果我有一个包含这些字节的缓冲区:
510175126-94-51080

如何从中提取75126-94-51部分(这是IP)并打印正确的IP?

for(int i = 0; i < bytes_recv; i++) { cout << static_cast(temp[i]); }cout<<结束;
编辑:这是我的输出:5 1 0 1 75 126 -94 -51 0 80

If I have a buffer containing these bytes:
510175126-94-51080

How can I extract the 75126-94-51 part from it(which is the IP) and print the correct IP?

for(int i = 0; i < bytes_recv; i++) { cout << static_cast<int>(temp[i]); } cout << endl;
edit: this is my output: 5 1 0 1 75 126 -94 -51 0 80

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

溇涏 2024-10-22 17:35:20

问题中缺少很多信息。因此,您正在读取来自 SOCKS 协议的服务器回复。首先,缓冲区不应该也不会具有 10 字节的固定大小。如果你的地址是 IPv4,它有 10 个字节(巧合的是,几天前它已经用完了,是时候考虑一​​下 IPv6 了)。如果源具有 IPv6 地址,则服务器响应的大小会有所不同。

RFC 1928 第 6 节开始,服务器回复具有以下格式:

<前><代码>+----+-----+--------+------+------------+-------- ----+
|版本|代表| RSV | ATYP | BND.地址| BND. 港口 |
+----+-----+--------+------+----------+------------+
| 1 | 1 | X'00'| 1 |变量| 2 |
+----+-----+--------+------+----------+------------+

请注意,地址字段的大小是可变的。具体来说,对于 IPv4,ATYP == 0x01 且 BND.ADDR 的大小为 4,这使得 1+1+1+1+4+2 = 10 字节。但您应该考虑其他大小也是可能的,特别是如果 ATYP == 0x03,这使得 BND.ADDR 的长度真正可变。

因此,在回答您的问题时,考虑到您在 char buffer[] 数组(或指针)中拥有这些字节,您必须首先检查地址的类型,然后像这样提取它:

#include <arpa/inet.h>

switch (buffer[3]) {
  case 0x01: {    /* IPv4 address */
    char result[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, (void*)(&buffer[4]), result, sizeof result);
    std::cout << "IPv4: " << result << "\n";
    break;
  }

  case 0x04: {    /* IPv6 address */
    char result[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET6, (void*)(&buffer[4]), result, sizeof result);
    std::cout << "IPv6: " << result << "\n";
    break;
  }

  default:
    std::cout << "Unsupported format.\n";
    break;
}

A lot of information is missing from the question. So, you are reading the server reply from the SOCKS protocol. First, the buffer should not and will not have a fixed size of 10 bytes. It has 10 bytes if your address is IPv4 (which coincidently was exhausted a few days ago, time to think about IPv6). If the origin has a IPv6 address, the size of the server response is different.

From RFC 1928, section 6, the server reply has this format:

+----+-----+-------+------+----------+----------+
|VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1  |  1  | X'00' |  1   | Variable |    2     |
+----+-----+-------+------+----------+----------+

Note that the address field has variable size. For IPv4, specifically, ATYP == 0x01 and BND.ADDR has size 4, which makes 1+1+1+1+4+2 = 10 bytes. But you should consider that other sizes are possible, specially if ATYP == 0x03, which makes BND.ADDR truly variable in length.

So, answering your question, considering that you have these bytes in a char buffer[] array (or pointer), you must first check the type of the address, then extract it like this:

#include <arpa/inet.h>

switch (buffer[3]) {
  case 0x01: {    /* IPv4 address */
    char result[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, (void*)(&buffer[4]), result, sizeof result);
    std::cout << "IPv4: " << result << "\n";
    break;
  }

  case 0x04: {    /* IPv6 address */
    char result[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET6, (void*)(&buffer[4]), result, sizeof result);
    std::cout << "IPv6: " << result << "\n";
    break;
  }

  default:
    std::cout << "Unsupported format.\n";
    break;
}
颜漓半夏 2024-10-22 17:35:20

在Python中:

input = '510175126-94-51080'
output = input[4:-3]

print output

In Python:

input = '510175126-94-51080'
output = input[4:-3]

print output
尘曦 2024-10-22 17:35:20

你如何获得这个缓冲区?它是 struct sockaddr_in 的一部分吗?

您是否显示从缓冲区最低地址开始的十进制字节转储?

您想要做的是获取指向 IP addr 部分的基(内存)地址的指针,并使用 ntohl() 将其转换为主机字节顺序,同样使用 ntohs code> 转换端口地址。

编辑

假设您

stuct sockaddr_in foo;
char str[16];
// do some stuff that initializes foo, e.g. a call to accept() returns

可以使用以下命令提取点分四组形式的 IP 地址

inet_ntop(AF_INET, &(foo.sin_addr), str, sizeof(str));

How are you getting this buffer? Is it part of a struct sockaddr_in?

Are you showing a decimal dump of bytes starting at the lowest address of the buffer?

What you want to do is get a pointer to the base (memory) address of the IP addr part and use ntohl() to translate it to host byte order, and likewise use ntohs to translate the port addr.

edit

Suppose you have

stuct sockaddr_in foo;
char str[16];
// do some stuff that initializes foo, e.g. a call to accept() returns

You can extract the IP address in dotted-quad form with

inet_ntop(AF_INET, &(foo.sin_addr), str, sizeof(str));
ゞ花落谁相伴 2024-10-22 17:35:20

如果您有以下缓冲区:

buffer[10] = {5, 1, 0, 1, 75, 126, 162, 205, 80, 00};

并且您希望在 C/C++ 中使用它。我将定义一个结构体,如下所示:

#pragma pack(1)
struct buffer_s {
    uint8_t  version;
    uint8_t  reserve_1;
    uint8_t  atype;
    uint32_t ip;
    uint16_t port;
};
#pragma pack()

然后将其放入联合中:

union buffer_u {
    char buffer[10];
    struct buffer_s data;
};

现在您可以声明 Union buffer_u buf 并将字节读取到 buf.buffer 中。然后对于 ip 和 port 字段,使用 ntohlntohs 将网络字节顺序转换为主机字节顺序。

If you have the following buffer:

buffer[10] = {5, 1, 0, 1, 75, 126, 162, 205, 80, 00};

And you want it in C/C++. I would define a struct, like this:

#pragma pack(1)
struct buffer_s {
    uint8_t  version;
    uint8_t  reserve_1;
    uint8_t  atype;
    uint32_t ip;
    uint16_t port;
};
#pragma pack()

Then put it in a union:

union buffer_u {
    char buffer[10];
    struct buffer_s data;
};

Now you can declare union buffer_u buf and read bytes into buf.buffer. Then for the ip and port fields use ntohl and ntohs to convert network byte order to host byte order.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文