⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 157.htm

📁 unix高级编程原吗
💻 HTM
📖 第 1 页 / 共 2 页
字号:
                fprintf( stderr, "-%02X", byteArray[i] ); <br>

            } <br>

            else <br>

            { <br>

            { <br>

                fprintf( stderr, " %02X", byteArray[i] ); <br>

            } <br>

        } <br>

        fprintf( stderr, "    " ); <br>

        i -= 16; <br>

        for ( j = 0; j < 16; j++, i++ ) <br>

        { <br>

            /* if ( isprint( (int)byteArray[i] ) ) */ <br>

            if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 ) ) <br>

            { <br>

                fprintf( stderr, "%c", byteArray[i] ); <br>

            } <br>

            else <br>

            { <br>

                fprintf( stderr, "." ); <br>

            } <br>

        } <br>

        fprintf( stderr, "\n" ); <br>

    }  /* end of for */ <br>

    k = byteArrayLen - i; <br>

    if ( k <= 0 ) <br>

    { <br>

    { <br>

        return; <br>

    } <br>

    fprintf( stderr, "%08X ", offset ); <br>

    for ( j = 0 ; j < k; j++, i++ ) <br>

    { <br>

        if ( j == 8 ) <br>

        { <br>

            fprintf( stderr, "-%02X", byteArray[i] ); <br>

        } <br>

        else <br>

        { <br>

            fprintf( stderr, " %02X", byteArray[i] ); <br>

        } <br>

    } <br>

    i -= k; <br>

    for ( j = 16 - k; j > 0; j-- ) <br>

    { <br>

        fprintf( stderr, "   " ); <br>

    } <br>

    fprintf( stderr, "    " ); <br>

    for ( j = 0; j < k; j++, i++ ) <br>

    { <br>

    { <br>

        if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 ) ) <br>

        { <br>

            fprintf( stderr, "%c", byteArray[i] ); <br>

        } <br>

        else <br>

        { <br>

            fprintf( stderr, "." ); <br>

        } <br>

    } <br>

    fprintf( stderr, "\n" ); <br>

    return; <br>

}  /* end of outputBinary */ <br>

int Socket ( int family, int type, int protocol ) <br>

{ <br>

    int n; <br>

    if ( ( n = socket( family, type, protocol ) ) < 0 ) <br>

    { <br>

        perror( "socket" ); <br>

        exit( FAILURE ); <br>

    } <br>

    return( n ); <br>

}  /* end of Socket */ <br>



int main ( int argc, char * argv[] ) <br>

{ <br>

    recvSocket = Socket( AF_INET, SOCK_RAW, IPPROTO_ICMP ); <br>

    while ( 1 ) <br>

    { <br>

        memset( packet, 0, 1500 ); <br>

        outputBinary( packet, recvfrom( recvSocket, packet, 1500, 0, NULL, N <br>

ULL <br>

) ); <br>

    } <br>

    Close( recvSocket ); <br>

    exit( SUCCESS ); <br>

}  /* end of main */ <br>

-------------------------------------------------------------------------- <br>

  <br>

可以参考阅读Phrack49-6、Phrack51-6两篇文章。 <br>

  <br>

上面的raw.c可以用于测试,现在简单讨论一下要实现的功能。一个rs和rc,rs接收 <br>

icmp echo request报文,从icmp数据区提取有效数据。icmp数据区可能需要自定义 <br>

格式(暂时不考虑加密传输的问题)。比如rs最后得到的指示是要做ls -la操作,那么 <br>

rs应该fork/exec执行/bin/sh -c "ls -la"这个命令。可能涉及到无名管道的技术。 <br>

rs将最终shell命令执行输出利用icmp echo reply负载发送到rc。rc负责接收用户输 <br>



入并利用icmp echo request负载发送到rs,还接收来自rs的icmp echo reply并提取 <br>

有效数据输出到标准输出。简单地、概括地讲,icmp pad backdoor就是这样的。具 <br>

体实现中可能有变化,核心部分不变,那就是利用icmp pad交换数据。 <br>

  <br>

另外有个想法,就是利用icmp pad建立一个通道,server host上运行一个daemon, <br>

client host上也运行一个daemon,假设server host位于firewall一侧,client <br>

host位于firewall另一侧。client创建一个tcp socket,监听7704端口, <br>

telnet client 7704,一切输入都被放入icmp pad,client向server发送icmp报文。 <br>

server创建一个tcp socket,连接到本机23端口。server接收icmp报文,提取icmp <br>

pad数据,发送到本机23端口。一切来自本机telnetd的数据都被放入icmp pad, <br>

server向client发送icmp报文。client接收icmp报文,提取icmp pad,从本机7704端 <br>

口上建立的连接发送出去,实际就是返回给最终用户。 <br>

  <br>

                            | <br>

user telnet 7704            |                  telnetd(23) <br>

    |                       |                      | <br>

    |                       |                      | <br>

client host ----------   firewall   ---------- server host <br>

listen 7704            允许icmp进出            connect 23 <br>

    |                       |                      | <br>

    |                       |                      | <br>

    ------------------- icmp tunnel ---------------- <br>



                            | <br>

                            | <br>

  <br>

防火墙设置了很多过滤规则,比如只允许http、icmp通过,此时上述icmp tunnel很 <br>

好用,可以根据不同需要修改server host上connect的目标端口。可以根据不同需要 <br>

安置client/server。client host总是代表最终用户可以直接访问的那一侧。 <br>

如果既要突破防火墙过滤规则,又要保证server host上的隐蔽性,至少不能被 <br>

netstat看出异常,上述icmp tunnel实现就需要修改。 <br>

  <br>

client --> server的时候使用icmp echo reply效果比较好。有些Linux可能做了设 <br>

置,不处理icmp echo request,但是icmp echo reply可以在没有出现过icmp echo <br>

request的情况下被发送被接收,而且也更容易突破防火墙。也可以不使用icmp echo, <br>

  <br>

但效果可能都不如icmp echo reply。server --> client的时候使用icmp echo <br>

request效果比较好,还是从突破防火墙角度考虑。暂时先这样考虑,以后实在不行 <br>

就提供参数设置。 <br>

  <br>

在SPARC/Solaris 2.6下man p2open看看,Linux下没有这个函数。编译的时候需要指 <br>

定-lgen开关。如果要在Linux实现同样功能,可能需要自己pipe、fork、dup2然后 <br>

exec? <br>

  <br>

根据p2open的man手册,应该没有重定向标准错误输出,既然如此,还是采用pipe方 <br>



式好些,可能将来移植方便吧。 <br>

  <br>

socket( AF_INET, SOCK_RAW, IPPROTO_ICMP )这种套接字,接收的时候对应整个IP <br>

报文,可以读取也必须读取整个IP报文,包括IP头;发送的时候如果没有额外设置 <br>

IP_HDRINCL选项,就不能干涉IP头部数据,sendto()参数中的指针指向ICMP数据区, <br>

而不是IP头,内核会构造IP头。 <br>

  <br>

ICMP报文头部的校验和包括ICMP数据区,也就是说对应整个ICMP报文。 <br>

因为使用到无名管道,应该处理SIGPIPE信号。很多问题靠man手册和例子代码是无法 <br>

理解的。一定要从实际编程、调试中才能找到问题、解决问题。这次的 <br>

raw_socket_server.c里处理SIGPIPE信号的技术比较典型,虽然不是最好的解决办法, <br>

但对于我们企图达到的效果足够了。首先设置忽略该信号,然后在write的返回值处 <br>

进行errno判断,如果EPIPE,就认为远程shell已经终止,此时我们关闭以前建立的 <br>

所有管道,重新创建新的管道,重新fork/exec出远程shell,这个远程shell的标准 <br>

输入/输出/错误输出都重定向过了。目前要尽量保持client/server均处在"无状态" <br>

中,避免操作的前后依赖性,否则很多地方处理复杂化。 <br>

  <br>

7.12注:上述这个设计文档的实战例子已经可用,所有提到的猜测和技术问题都得到 <br>

        实践验证,所以,如果你要写自己的icmp tunnel,可以开工了。上面没有 <br>

        提到的就是需要加密传输、口令验证。 <br>

<待续> <br>

-- <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="8.htm">上一层</a>][<a href="158.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -