Android ndc命令没有,ndc.c - Android社区 - https://www.androidos.net.cn/

本文介绍了一个用于与Netd服务进行交互的C/C++客户端程序。该程序通过本地socket连接到Netd服务,并支持发送命令及监控模式。文章详细展示了程序的实现细节,包括命令行参数处理、命令构造及发送、响应接收等。

/*

* Copyright (C) 2008 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

#include #include #include #include #include #include #include #include #include #include #include #include #include #include static void usage(char *progname);

static int do_monitor(int sock, int stop_after_cmd);

static int do_cmd(int sock, int argc, char **argv);

int main(int argc, char **argv) {

int sock;

int cmdOffset = 0;

if (argc < 2)

usage(argv[0]);

// try interpreting the first arg as the socket name - if it fails go back to netd

if ((sock = socket_local_client(argv[1],

ANDROID_SOCKET_NAMESPACE_RESERVED,

SOCK_STREAM)) < 0) {

if ((sock = socket_local_client("netd",

ANDROID_SOCKET_NAMESPACE_RESERVED,

SOCK_STREAM)) < 0) {

fprintf(stderr, "Error connecting (%s)\n", strerror(errno));

exit(4);

}

} else {

if (argc < 3) usage(argv[0]);

printf("Using alt socket %s\n", argv[1]);

cmdOffset = 1;

}

if (!strcmp(argv[1+cmdOffset], "monitor"))

exit(do_monitor(sock, 0));

exit(do_cmd(sock, argc-cmdOffset, &(argv[cmdOffset])));

}

static int do_cmd(int sock, int argc, char **argv) {

char *final_cmd = strdup("0 ");

if (final_cmd == NULL) {

perror("strdup");

return errno;

}

int i;

for (i = 1; i < argc; i++) {

if (index(argv[i], '"')) {

perror("argument with embedded quotes not allowed");

free(final_cmd);

return 1;

}

bool needs_quoting = index(argv[i], ' ');

const char *format = needs_quoting ? "%s\"%s\"%s" : "%s%s%s";

char *cmp;

if (asprintf(&cmp, format, final_cmd, argv[i],

(i == (argc -1)) ? "" : " ") < 0) {

perror("malloc");

free(final_cmd);

return errno;

}

free(final_cmd);

final_cmd = cmp;

}

if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) {

perror("write");

free(final_cmd);

return errno;

}

free(final_cmd);

return do_monitor(sock, 1);

}

static int do_monitor(int sock, int stop_after_cmd) {

char *buffer = malloc(4096);

if (!stop_after_cmd)

printf("[Connected to Netd]\n");

while(1) {

fd_set read_fds;

struct timeval to;

int rc = 0;

to.tv_sec = 10;

to.tv_usec = 0;

FD_ZERO(&read_fds);

FD_SET(sock, &read_fds);

if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {

fprintf(stderr, "Error in select (%s)\n", strerror(errno));

free(buffer);

return errno;

} else if (!rc) {

continue;

fprintf(stderr, "[TIMEOUT]\n");

return ETIMEDOUT;

} else if (FD_ISSET(sock, &read_fds)) {

memset(buffer, 0, 4096);

if ((rc = read(sock, buffer, 4096)) <= 0) {

if (rc == 0)

fprintf(stderr, "Lost connection to Netd - did it crash?\n");

else

fprintf(stderr, "Error reading data (%s)\n", strerror(errno));

free(buffer);

if (rc == 0)

return ECONNRESET;

return errno;

}

int offset = 0;

int i = 0;

for (i = 0; i < rc; i++) {

if (buffer[i] == '\0') {

int code;

char tmp[4];

strncpy(tmp, buffer + offset, 3);

tmp[3] = '\0';

code = atoi(tmp);

printf("%s\n", buffer + offset);

if (stop_after_cmd) {

if (code >= 200 && code < 600)

return 0;

}

offset = i + 1;

}

}

}

}

free(buffer);

return 0;

}

static void usage(char *progname) {

fprintf(stderr, "Usage: %s [sockname] |[arg1] [arg2...]\n", progname);

exit(1);

}

C++程序

|

174行

|

4.86 KB

/*

* Copyright (C) 2008 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

static void usage(char *progname);

static int do_monitor(int sock, int stop_after_cmd);

static int do_cmd(int sock, int argc, char **argv);

int main(int argc, char **argv) {

int sock;

int cmdOffset = 0;

if (argc < 2)

usage(argv[0]);

// try interpreting the first arg as the socket name - if it fails go back to netd

if ((sock = socket_local_client(argv[1],

ANDROID_SOCKET_NAMESPACE_RESERVED,

SOCK_STREAM)) < 0) {

if ((sock = socket_local_client("netd",

ANDROID_SOCKET_NAMESPACE_RESERVED,

SOCK_STREAM)) < 0) {

fprintf(stderr, "Error connecting (%s)\n", strerror(errno));

exit(4);

}

} else {

if (argc < 3) usage(argv[0]);

printf("Using alt socket %s\n", argv[1]);

cmdOffset = 1;

}

if (!strcmp(argv[1+cmdOffset], "monitor"))

exit(do_monitor(sock, 0));

exit(do_cmd(sock, argc-cmdOffset, &(argv[cmdOffset])));

}

static int do_cmd(int sock, int argc, char **argv) {

char *final_cmd = strdup("0 ");

if (final_cmd == NULL) {

perror("strdup");

return errno;

}

int i;

for (i = 1; i < argc; i++) {

if (index(argv[i], '"')) {

perror("argument with embedded quotes not allowed");

free(final_cmd);

return 1;

}

bool needs_quoting = index(argv[i], ' ');

const char *format = needs_quoting ? "%s\"%s\"%s" : "%s%s%s";

char *cmp;

if (asprintf(&cmp, format, final_cmd, argv[i],

(i == (argc -1)) ? "" : " ") < 0) {

perror("malloc");

free(final_cmd);

return errno;

}

free(final_cmd);

final_cmd = cmp;

}

if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) {

perror("write");

free(final_cmd);

return errno;

}

free(final_cmd);

return do_monitor(sock, 1);

}

static int do_monitor(int sock, int stop_after_cmd) {

char *buffer = malloc(4096);

if (!stop_after_cmd)

printf("[Connected to Netd]\n");

while(1) {

fd_set read_fds;

struct timeval to;

int rc = 0;

to.tv_sec = 10;

to.tv_usec = 0;

FD_ZERO(&read_fds);

FD_SET(sock, &read_fds);

if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {

fprintf(stderr, "Error in select (%s)\n", strerror(errno));

free(buffer);

return errno;

} else if (!rc) {

continue;

fprintf(stderr, "[TIMEOUT]\n");

return ETIMEDOUT;

} else if (FD_ISSET(sock, &read_fds)) {

memset(buffer, 0, 4096);

if ((rc = read(sock, buffer, 4096)) <= 0) {

if (rc == 0)

fprintf(stderr, "Lost connection to Netd - did it crash?\n");

else

fprintf(stderr, "Error reading data (%s)\n", strerror(errno));

free(buffer);

if (rc == 0)

return ECONNRESET;

return errno;

}

int offset = 0;

int i = 0;

for (i = 0; i < rc; i++) {

if (buffer[i] == '\0') {

int code;

char tmp[4];

strncpy(tmp, buffer + offset, 3);

tmp[3] = '\0';

code = atoi(tmp);

printf("%s\n", buffer + offset);

if (stop_after_cmd) {

if (code >= 200 && code < 600)

return 0;

}

offset = i + 1;

}

}

}

}

free(buffer);

return 0;

}

static void usage(char *progname) {

fprintf(stderr, "Usage: %s [sockname] | [arg1] [arg2...]\n", progname);

exit(1);

}

<think>我们被要求解释这个URL:http://<服务器地址>/index.php?page=php://filter/convert.base64-encode/resource=flag.php 这个URL用于利用文件包含漏洞读取服务器上的flag.php文件的内容,并且通过Base64编码的方式获取,以避免直接执行PHP代码。 我们将URL拆解为几个部分,逐一解释: 1. 协议和域名(或IP地址)部分:`http://<服务器地址>/` - 这是目标Web服务器的基础地址。 2. 路径部分:`index.php` - 这是服务器上的一个PHP脚本文件,通常是一个包含文件包含漏洞的脚本(例如,它可能使用`include`或`require`函数包含`page`参数指定的文件)。 3. 查询字符串(Query String)部分:以`?`开始,后面是参数。这里只有一个参数`page`,其值是一个很长的字符串。 - 查询字符串的格式是`key=value`,多个参数用`&`分隔。 4. 参数`page`的值:`php://filter/convert.base64-encode/resource=flag.php` - 这个值是一个PHP流(Stream)的封装器(Wrapper),具体是`php://filter`,它允许我们对数据流进行过滤处理。 - 分解这个值: - `php://filter/`:这是PHP的流包装器,用于对数据流进行过滤。 - `convert.base64-encode`:这是应用到流上的过滤器,表示将资源的内容进行Base64编码。 - `resource=flag.php`:指定要读取的资源,即当前目录(或绝对路径)下的`flag.php`文件。 所以,整个URL的作用是:访问服务器上的`index.php`脚本,并将`page`参数设置为一个经过Base64编码处理的`flag.php`文件。这样,`index.php`脚本在包含文件时,会读取`flag.php`文件的内容,并对其进行Base64编码,然后将编码后的内容输出到响应中。 为什么需要Base64编码? - 因为如果直接包含`flag.php`,其中的PHP代码会被服务器执行,而我们可能无法看到完整的源代码(特别是当文件中包含一些不输出的内容,比如flag在注释中)。通过Base64编码,我们可以获取文件的原始内容的编码形式,然后解码即可得到完整的源代码。 使用步骤: 1. 在浏览器中访问这个URL(替换`<服务器地址>`为实际地址)。 2. 服务器返回Base64编码的字符串。 3. 将返回的Base64字符串解码,即可得到`flag.php`的源代码。 注意:这种利用方式需要`index.php`脚本存在文件包含漏洞,并且允许使用`php://filter`伪协议。 示例: 假设服务器地址是`example.com`,我们构造的URL为: http://example.com/index.php?page=php://filter/convert.base64-encode/resource=flag.php 访问后,我们可能会在页面上看到类似这样的输出: PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7ZWE4OGE2ZTQtY2RmYi00NDc4LWFjMGQtNTk2NzAyM2E2MWRifQo= 然后使用Base64解码(可以在线解码或使用命令行工具)得到: <?php echo "Can you find out the flag?"; //flag{ea88a6e4-cdfb-4478-ac0d-5967023a61db} 这样我们就从注释中获取了flag。 相关问题: 1. 除了Base64编码,`php://filter`还可以使用哪些过滤器? 2. 如何防御文件包含漏洞? 3. 在CTF中,还有哪些常见的伪协议利用方式? 4. 如果目标服务器禁用了`php://filter`伪协议,还有哪些方法可以读取文件源码?</think>### URL 参数解析:`http://<服务器地址>/index.php?page=php://filter/convert.base64-encode/resource=flag.php` 此 URL 是典型的**文件包含漏洞利用链**,通过伪协议绕过文件读取限制。以下是各字段的详细作用: --- #### 1. **基础路径部分** - `http://<服务器地址>/index.php` 目标服务器的入口文件,通常存在文件包含漏洞(如 `include($_GET['page'])`)[^1]。 --- #### 2. **查询参数 `?page=`** - `page=` 漏洞触发点参数名(常见如 `page`, `file`, `include`)。 服务器通过此参数动态包含文件(如 `include($_GET['page'])`),但未过滤用户输入[^2]。 --- #### 3. **伪协议 `php://filter`** - `php://filter/` PHP 内置的流过滤器协议,允许对数据流进行实时处理(如编码/解码/压缩)[^3]。 **作用**:绕过文件包含限制,直接读取文件原始内容而非执行 PHP 代码。 --- #### 4. **过滤器链 `convert.base64-encode`** - `convert.base64-encode` 将文件内容转换为 Base64 编码的过滤器。 **作用**: - 避免 PHP 文件被服务器执行(否则仅输出 `echo` 内容)。 - 防止特殊字符(如 `<?php ?>`)破坏输出结构。 - 确保二进制文件(如图片)可完整传输[^2]。 --- #### 5. **资源定位 `resource=flag.php`** - `resource=flag.php` 指定目标文件路径(此处为根目录下的 `flag.php`)。 **关键特性**: - 支持相对路径(如 `resource=../config.php`)[^3]。 - 可绕过路径限制(如 `resource=/var/www/html/flag.php`)。 --- ### 完整工作流程 1. 用户请求 URL → 服务器执行 `index.php`。 2. `include($_GET['page'])` 加载 `php://filter` 流。 3. 过滤器对 `flag.php` 进行 Base64 编码 → 输出编码后字符串。 4. 用户解码 Base64 获取原始文件内容(含 flag 注释)[^1]。 ```mermaid graph LR A[用户请求] --> B[index.php?page=...] B --> C{php://filter} C --> D[convert.base64-encode] D --> E[读取 resource=flag.php] E --> F[输出Base64字符串] F --> G[用户解码得flag] ``` --- ### 防御建议 1. **禁用危险协议**: `php.ini` 中设置 `allow_url_include=Off`。 2. **输入过滤**: 用白名单限制包含文件(如 `if($page=='home') include('home.php')`)。 3. **目录限制**: 使用 `open_basedir` 约束文件访问范围。 --- ### 相关问题 1. 如何通过 `php://filter` 读取 `/etc/passwd` 文件? 2. 除了 Base64,还有哪些过滤器可用于文件包含漏洞(如 `string.rot13`)? 3. 如何利用 `zip://` 或 `phar://` 伪协议实现文件包含? 4. 在文件包含漏洞中,`../` 路径遍历攻击如何防御? [^1]: 文件包含漏洞利用示例 [^2]: PHP 伪协议过滤器原理 [^3]: 路径遍历与资源定位技巧
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值