CS 519419 Cyber Attacks Defense Shellcoding 2 101618
CS 519/419 Cyber Attacks & Defense Shellcoding - 2 10/16/18
Shellcode Tricks • Symlink • An alias of a file • You can set a new name of a file… • ‘/bin/sh’ -> ‘A’: how many bytes can you reduce?
Reuse Existing Values • In short-shellcode-32, main() Calls shellcode here!
EBX is zero ECX points to some string. . Reuse Existing Values. ESI points to some string. . • Run and si. .
Alphanumeric • int $0 x 80 • cd 80 • Non-ASCII, non-printable, non-alphanumeric • How?
Alphanumeric • Create cd 80 from alphanumeric values • . byte: puts raw bytes, in assembly • . byte 0 x 32 (‘ 0’) • . byte 0 x 7 a (‘z’) • Can we create cd 80 by applying some operations on such 0 x 32, 0 x 7 a?
Alphanumeric XOR 0 xff Alpha-numeric code Execute CD 80, int $0 x 80! XOR 0 xfa 0 xcd 0 x 32 0 x 7 a 0 x 80 We call this as ‘self modifying code’…
Helpful Instructions Make eax -1 only with alphanumeric… j. AX 4 AH 0 xff ^ 0 x 32 = 0 xcd, “f 1 BA” Mov registers with push & pop = “PY” Make ecx 0 xfa (0 xff+6 = 0 xfa. . ) 0 xff ^ 0 x 7 a = 0 x 80, “ 0 JB” Do not use pop %ebx. Use popa…
Stack • Used for • Storing local variables • Your input buffer could be here… • Passing function arguments • Storing return address • Storing frame pointer (i. e. , saved %ebp) • What others? • filename • ARGV • ENVP
How Linux Runs a Program? • Reading: • How programs get run: ELF binaries • https: //lwn. net/Articles/631631/ • ELF (Executable and Linkable Format) • Basics: • execve(char *name, char** argv, char **envp) • execve(“program path”, argument_vectors, environment_pointers) • execve(“/bin/sh”, {“sh”, NULL}, {”SHELL=sh”, “TERM=xterm”, …, NULL});
execve() • Takes 3 arguments • Program path: program to execute; could be an ELF file • /bin/sh /bin/ls /usr/bin/python • Argument vectors: list of arguments, each as string • • That’s why it is char **argv When running “python a. py 1 2 3”, argv[0] = “python” argv[1] = “a. py” argv[2] = “ 1” argv[3] = ” 2” argv[4] = “ 3”
execve() • Takes 3 arguments • Program name: program to execute; could be an ELF file • Argument vectors: list of arguments, each as string • Environment Variables: list of environments variables, each as string • • Also char **envp “TERM=xterm” “SHELL=sh” “EDITOR=/usr/bin/vim”
execve() • Takes 3 arguments • Program name: program to execute; could be an ELF file • Argument vectors: list of arguments, each as string • Environment Variables: list of environments variables, each as string • • Also char **envp “TERM=xterm” “SHELL=sh” “EDITOR=/usr/bin/vim”
1. Load the Executable • From the program path (1 st arg to execve), the kernel loads code and data to the memory space • execve(“/bin/sh”, …. ) Program Path “/bin/sh” • Code section • Usually starts from 0 x 8048000 (32 bit), or 0 x 400000 (64 bit) • readelf -a /bin/sh • Will store the path name of the program at the bottom of the stack
2. Set Environment Variables • Set environmental variables to the current stack. Program Path “/bin/sh” ENV 1 ENV 2 ENV 3 … ENV Ptrs
2. Set Environment Variables • Set environmental variables to the current stack. Program Path “/bin/sh” ENV 1 ENV 2 ENV 3 … ENV Ptrs
3. Set Argument Vectors • Set argument vectors to the current stack. • • • When running “python a. py 1 2 3”, argv[0] = “python” argv[1] = “a. py” argv[2] = “ 1” argv[3] = ” 2” argv[4] = “ 3” Program Path “/bin/sh” ENV 1 ENV 2 ENV 3 … ENV Ptrs ARGV 4 ARGV 3 … ARGV Ptrs
4. Call _start • readelf -a …
4. Call _start • readelf -a … Addr of _start()
4. Call _start • readelf -a … Addr of main()
4. Call _start • readelf -a … • Calls __libc_start_main • And then, libc_start_main sets the address of argv, envp, then calls main(argc, argv, envp) Program path ENVS ENVP Ptrs ARGV Ptrs … ENVP ARGV ARGC The stack of main() starts at here:
Check with GDB • b main • r • x/100 x $esp
Stack-ovfl-* for Week 3 • Contains a buffer overflow vulnerability • DO NOT contains get_a_shell() • You should put your shellcode on the stack and jump to there…
How Can You Put Your Shellcode? • make print • Send it to the binary via pwntool (writing to the buffer)
How Can You Put Your Shellcode? • What if it does not let you know or use buffer? • Put your shellcode as an environment variable • env = {’SHELLCODE’ : SHELLCODE} • Put your shellcode as a program argument
Getting the Shellcode Address • Use GDB with core! • c = Core(‘core’) • c. stack. find(SHELLCODE)
Running Shellcode Return to here executes shellcode SHELLCODE Fails • Requires an exact address of a shellcode… Fails
NOP-sled Return to here executes shellcode NOP Sled (full of 0 x 90 s) SHELLCODE Fails • nop • An instruction that does nothing • Opcode is 0 x 90 Fails
NOP-sled Trick NOP Sled (full of 0 x 90 s) SHELLCODE • SHELLCODE = “x 90” * 500 + SHELLCODE • Return to anywhere at the NOP-sled (sized 500 in this case) will let you run the shellcode!
Assignment: Week-3 • stack-ovfl-sc: put your shellcode on your input buffer • stack-ovfl-use-envp: put your shellcode on envp • stack-ovfl-no-envp: put your shellcode on argv • stack-ovfl-no-envp-no-argv: put your shellcode as the filename. . • stack-ovfl-where: Extra-credit (20+) • Due: 10/23 2: 00 pm
- Slides: 30