AI 摘要(由 ChatGPT 总结生成):
本文介绍了一种使用 Bash 脚本模拟 HTTP 和 HTTPS 请求的方法,适用于缺少 wget 和 curl 命令的环境。文章提供了详细的脚本代码和使用方法,通过示例展示了脚本的效果和使用方法,包括如何处理 HTTP 和 HTTPS 协议。这种方法能够替代传统的 wget 和 curl 命令,实现网络请求的功能。

前言

之前写过一篇文章关于使用纯 Bash 模拟 HTTP 请求的文章,链接如下:

正好前阵子又分析了一个恶意挖矿脚本时遇到了一段相关代码,遂有感而发。

而且平时我们拿到一个 Shell ,进去后发现没有 wgetcurl 命令(特别是一些阉割较狠的 Docker 容器环境内),但是却具有完整的 Bash 环境,这时候我们可不可以使用 Bash 的特性,使得我们可以使用类似 wgetcurl 命令呢?这就是今晚水这篇文章的原因。废话不多说,直接上代码及食用教程。

代码

脚本代码比较粗糙,未做更好的优化,更多的是提供大家一个思路。

代码如下:

#!/bin/bash

_curl() {
    local proto server path port
    proto=$(echo "$1" | awk -F: '{print $1}')
    server=$(echo "$1" | awk -F/ '{print $3}')
    path=$(echo "$1" | awk -F/ '{for(i=4;i<=NF;i++) printf "%s", $i; print ""}')

    local tag="close"
    local ua="curl/7.29.0 (Shell)"
    DOC="/${path}"
    HOST="${server%%:*}"
    PORT="${server##*:}"

    if [[ "$proto" == "http" ]]; then
        [[ "$PORT" == "$HOST" ]] && PORT=80
        exec 3<>/dev/tcp/${HOST}/$PORT
        FD_IN=3
    elif [[ "$proto" == "https" ]]; then
        [[ "$PORT" == "$HOST" ]] && PORT=443

        # 对于 HTTPS 使用 coproc 创建子进程运行,避免脚本卡住
        coproc openssl_process { openssl s_client -connect ${HOST}:${PORT} -quiet 2>/dev/null; }
        exec 3>&${openssl_process[1]}
        exec 4<&${openssl_process[0]}
        FD_IN=4
    else
        echo "错误:不支持的协议。请使用 http 或 https。"
        exit 1
    fi

    echo -en "GET ${DOC} HTTP/1.1\r\nHost: ${HOST}\r\nUser-Agent: ${ua}\r\nConnection: ${tag}\r\n\r\n" >&3

    local chunked=false
    while read -r line <&${FD_IN}; do
        line="${line%%[[:cntrl:]]}"
        [[ -z "$line" ]] && break
        [[ "$line" =~ Transfer-Encoding:\ chunked ]] && chunked=true
    done

    if $chunked; then
        _parse_chunked_body
    else
        cat <&${FD_IN}
    fi
    exec 3>&-
    [[ "$proto" == "https" ]] && { exec 4<&-; wait $openssl_process_PID; }
}

_parse_chunked_body() {
    while :; do
        read -r chunk_size_hex <&${FD_IN}
        chunk_size_hex="${chunk_size_hex%%[[:cntrl:]]}"
        local chunk_size=$((16#$chunk_size_hex))
        [[ $chunk_size -eq 0 ]] && break
        dd bs=1 count=$chunk_size <&${FD_IN} 2>/dev/null
        read -r _ <&${FD_IN}
    done
}

if [[ -z "$1" ]]; then
    echo "错误:未提供 URL 参数。"
    echo "用法示例:$0 http(s)://example.com/path"
    exit 1
else
    _curl "$1"
fi

食用

可将上述代码保存到 Shell 脚本中或自行集成到自己的脚本中,食用方法如下(同步食用自带的 curl 命令模拟一遍做对照参考):

  • HTTP 方式模拟如下:
[root@localhost tmpdir]# curl http://ip.isisy.com/8.8.8.8
IP: 8.8.8.8
AS: AS15169
City: Mountain View
Region: California
Country: US - United States(美国)
Timezone: America/Los_Angeles
Location: 37.4056,-122.0775
ISP: Google LLC
Scope: 8.8.8.8/32
Detail: 美国–加利福尼亚州–圣克拉拉–山景城谷歌公司DNS服务器
[root@localhost tmpdir]# 
[root@localhost tmpdir]# ./_curl.sh http://ip.isisy.com/8.8.8.8
IP: 8.8.8.8
AS: AS15169
City: Mountain View
Region: California
Country: US - United States(美国)
Timezone: America/Los_Angeles
Location: 37.4056,-122.0775
ISP: Google LLC
Scope: 8.8.8.8/32
Detail: 美国–加利福尼亚州–圣克拉拉–山景城谷歌公司DNS服务器
[root@localhost tmpdir]# 
  • HTTPS 方式模拟如下:
[root@localhost tmpdir]# curl https://ip.isisy.com/robots.txt
User-Agent: *
Disallow: /
[root@localhost tmpdir]# 
[root@localhost tmpdir]# ./_curl.sh https://ip.isisy.com/robots.txt
User-Agent: *
Disallow: /
[root@localhost tmpdir]# 

可见请求结果基本一致,使用上述脚本时,还请使用完整的 HTTP(S) 链接,同时用户也可自己定义其请求端口,例如:

./_curl.sh http://example:8080/path

小结

本脚本基本实现了使用 Bash 的相关特性以请求网络地址,但还有较多待完善的地方,若其他大佬有兴趣可接着完善(或等我后续在慢慢完善~)。

End

本文标题:Bash 模拟 HTTP(S) 的脚本方式实现

本文链接:https://www.isisy.com/1577.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

如果觉得我的文章对你有用,请随意赞赏