软件作者:Goldberg [安全矩阵](
www.smatrix.org)
信息来源:
黑基论坛
题外话:前段时间用C做了个windows环境下的远程控制小软件(
http://bbs.hackbase.com/viewthread-2949463-1.html),这次这个软件仍然是用C编的,可以在linux环境下实现:下载文档,编辑文档,关闭远程主机,重新启动远程主机,修改管理员密码这五个功能.
由于编程只是本人的业余爱好,水平实在有限,所以软件做的比较垃圾,希望各位高手不吝赐教
此软件只能在linux环境下运行.
服务器实现的关键代码如下:
int main(int argc, char** argv)
//argc为参数的个数,argv[0]对应程序, argv[1]对应-p, argv[2]对应端口号
{
………………………………
if (argc != 3 || strcmp(argv[1], "-p") || (port = atoi(argv[2])) < 1024) {
//argc不为0,或argv[1]不为-p,或端口号<1024,则退出
………………………………
}
if (uname(&myname) < 0 || (he = gethostbyname(myname.nodename)) == NULL) {
//获得主机名
………………………………
}
hostaddr = *(unsigned long *)(he->h_addr);
listen_fd = init_socket(port);
//初始化套接字,创建,绑定并监听socket
if ((p = strrchr(argv[0], '/')) != NULL)
//取得”/”最后一次出现处到結尾的字串,即程序名,赋值给p
p ++;
else
p = argv[0];
//如果p为NULL,则argv[0]就是程序名, 赋值给p
sprintf(root_path, "/app/%s", p); //路径:app下的程序名
p = argv[0] + strlen(argv[0]) - 1;
while (*p && *p != '/') {
*p = toupper(*p); //将字符转化为大写英文字符
p --;
}
daemon( 1, 1 ); //守护程序
syslog(LOG_ERR, "*** Starting %s on %s ***", p + 1, inet_ntoa(*(struct in_addr *)&hostaddr)); //在系统日志中写入相关信息
………………………………
for (;;) {
FD_ZERO( &afdset );
//afdset为文件描述符集,现清空afdset与所有文件句柄的联系。
maxfd = -1;
FD_SET( listen_fd, &afdset ); //加入套接字
if ( listen_fd > maxfd )
maxfd = listen_fd; //将maxfd的值始终保持最大值
if (select(maxfd + 1, &afdset , NULL, NULL, NULL) < 0)
continue;
………………………………
if (FD_ISSET( listen_fd, &afdset ) )
conn_fd = accept( listen_fd, (struct sockaddr *)&usa, &sz );
//返回值 成功:返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了。即 conn_fd = listen_fd。
失败:返回-1。即conn_fd = -1。
else
continue;
………………………………
if ((r = fork()) < 0 ) {
//fork( )的主要任务是初始化要创建进程的数据结构. 当fork()!=0 的时候,表明是父进程,要终止
………………………………
} else if ( r == 0 ) {
//当fork()==0 的时候,表明是子进程,执行
client_addr = usa;
close( listen_fd );
//将套接口做上“已关闭的标记”,并立即返回进程
get_http(); //通过该函数获得HTTP协议的请求方法,并调用do_cgi()
exit( 0 );
}
close( conn_fd );
}
}
下载文档功能实在的关键代码如下:
my_cgi()
{………………………………
else if (strcmp(p, "download") == 0)
//判断表单变量,如果是download则运行down_load函数
down_load(); //显示下载文档界面,并指定对演示文档的操作方式
………………………………
}
static down_load()
{………………………………
if ((p = getenv("PATH_INFO")) == NULL ||
strncmp(p, "/demo/", 6) != 0) {
disp_file_menu(0);
//通过判断路径信息和文档信息,调用disp_file_menu(0),参数0表示出现下载文档界面
return;
}
if ((fp = fopen(fn, "r")) != NULL) { // fopen(fn, "r")表示以只读方式打开文件fn
while ((i = fread(buf, 1, 4096, fp)) > 0)
fwrite(buf, 1, i, stdout);
fclose(fp); //对所选择的文档进行下载
………………………………
}
编辑文档功能实现的关键代码如下:
void edit_file()
{ ………………………………
disp_file_menu(1);
//通过判断路径信息和文档信息,调用disp_file_menu(1),参数1表示出现编辑文档界面
………………………………
disp_edit_file(0);
//对文档的状态进行判断,当参数为1,3,9分别执行相应动作,其它参数则不执行动作
………………………………
disp_edit_file(1); //参数为1,返回”主机连接失败”
………………………………
disp_edit_file(9); //参数为9,返回”文件修改成功”
………………………………
}
void disp_edit_file(int type)
{………………………………
printf("<script language=\"javascript\">\n");
printf("function thisform_OnSubmit()\n");
//修改文档后,按下“确定”按钮执行javascript脚本程序,保存修改后的文档
printf("{\n");
printf(" return confirm(\"保存修改后的文档吗?\");\n");
printf("}\n");
printf("</script>\n");
………………………………
if (type == 1) //针对不同的type值返回不同的反馈信息
printf("<p align=\"center\"><strong><font color=\"#FF0000\">主机连接失败!</font></strong></p>\n");
else if (type == 3)
………………………………
else if (type == 9)
………………………………
}
关闭远程主机功能实现的关键代码如下:
void host_stop()
{
if (get_form("stat") == NULL) {
disp_host_control_hoststop(); //显示关闭主机界面
return;
}
execlp("init", "init", "0", 0); //将execlp的第三个参数设置为0,远程关闭主机
重新启动远程主机功能实现的关键代码如下:
void host_restart()
{
if (get_form("stat") == NULL) {
disp_host_control_hostrestart(); //显示热启动主机界面
return;
}
execlp("init", "init", "6", 0); //将execlp的第三个参数设置为6,重新启动系统
}