Where am I going wrong with my experimentation:
I am trying to experimentally deduce the details of creating a simple shellcode. My first impression was I probably would not be able to use imports, as my shellcode is not linked by the compiler of the target program. I then began wondering how small I can make a simple shell command interface over a socket without using imports, so I wrote up some code; and started ignoring implicit call warnings:
// socket_family
#define AF_INET 2
#define AF_PACKET 17
// socket_type
#define SOCK_STREAM 1
typedef unsigned short sa_family_t;
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
struct in_addr {
unsigned long s_addr; // load with inet_pton()
};
struct sockaddr_in {
short sin_family; // e.g. AF_INET, AF_INET6
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, above
char sin_zero[8]; // zero this if you want to
};
int main(void) {
int sfd;
const short family = AF_INET;
const char host[] = "127.0.0.1";
struct sockaddr addr;
struct sockaddr_in *addr_full = (struct sockaddr_in*)&addr;
if (sfd = socket(family, SOCK_STREAM, 0) < 0) return 1;
memset(&addr, 0, sizeof(struct sockaddr));
addr_full->sin_family = family;
addr_full->sin_port = htons(8000);
inet_pton(family, host, &(addr_full->sin_addr.s_addr));
if (connect(sfd, &addr, sizeof(struct sockaddr)) < 0) return 2;
close(sfd);
return 0;
}
Somewhere along the line I am not connecting to my python -m SimpleHTTPServer properly; which reports Serving HTTP on 0.0.0.0 port 8000.
$ gcc my_program.c -o my_program
$ ./my_program
$ echo $?
2
I am taking a Coursera course on software security; and a lot of this topic is new to me.
EDIT:
After removing redefinitions and adding includes:
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
int main(void) {
int sfd;
const short family = AF_INET;
const char host[] = "127.0.0.1";
struct sockaddr_in addr_full; // = (struct sockaddr_in*)&addr;
if (sfd = socket(family, SOCK_STREAM, 0) < 0) return 1;
memset(&addr_full, 0, sizeof(struct sockaddr));
addr_full.sin_family = family;
addr_full.sin_port = htons(8000);
inet_pton(family, host, &(addr_full.sin_addr.s_addr));
if (connect(sfd, (struct sockaddr*)&addr_full, sizeof(struct sockaddr)) < 0) return 2;
close(sfd);
return 0;
}
The program still exits with 2.
The socket file descriptor was not being assigned properly. Adding parenthesis, I should be assigning the descriptor, then checking its value:
if ((sfd = socket(family, SOCK_STREAM, 0)) < 0) return 1;
Motoko,
please grab C language book and check operations priority. And do it regulary, even experienced developers make errors here. And don't write this crazy style, please learn how to write for humans:
if (sfd = socket(family, SOCK_STREAM, 0) < 0) return 1;
You should instead do something like this:
sfd = socket(family, SOCK_STREAM, 0);
if (sfd < 0)
{
/* perror() is pretty old style but some good check is recommended. */
perror("socket");
return 1;
}
SPOILER: < just has higher priority here so sfd is always 0 in your code.
Your assumption about the include files is wrong. The include files only contain the function declarations, not the code itself. They don't determine how your program will get linked to shared libraries.
Include files only tell the compiler that the functions you call inside your program exist somewhere, in some external library or in another source file you wrote. After compilation the linker tries to find all the functions that your program needs, and if they are not found, linking fails.
Try compiling your code with the necessary files included (socket.h etc.). This will give you useful warnings, for example when you pass an argument of the wrong type.
Related
I have a variable of in_addr_t type and I would like to use connect() with the given ip. I'm therefore needing a (struct sockaddr *) variable as parameter for the connect(). How to insert use the in_addr_t variable instead?
in_addr_t var; // Given variable, not actually declared here ofc
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in *srvraddr = malloc(sizeof(struct sockaddr_in));
memset((void *) srvraddr, 0, sizeof(struct sockaddr_in));
srvraddr->sin_family = AF_INET;
srvraddr->sin_port = htons(PORT_A); // Big - little endian arch compatibility
srvraddr->sin_addr.s_addr = var; // Somehow assign var here? <<<<<
connect(sockfd, (struct sockaddr *) srvraddr, sizeof(struct sockaddr_in));
Whatever I try to do connect always returns me -1.
Using perror I get the following error: Connection refused.
How to insert use the in_addr_t variable instead?
You cannot use an in_addr_t with connect() instead of a struct sockaddr_in. connect() accepts varying address structure types, but not arbitrary ones. The correct structure type for an IPv4 address is the struct sockaddr_in that you're already using. You need to store an appropriate representation of the remote host address into that.
Evidently, you already have an in_addr_t that you assert represents the remote address, but are uncertain how to use it:
in_addr_t var; // Given variable, not actually declared here ofc
[...]
srvraddr->sin_addr.s_addr = var; // Somehow assign var here? <<<<<
What you present is already exactly what POSIX expects you to do, however. POSIX requires that the sin_addr member of a struct sockaddr_in be a structure having at minimum a s_addr member of type in_addr_t. Supposing that the in_addr_t you have is in fact a correct representation of the machine address to which you want to connect, assigning that value to sin_addr.s_addr of your address structure is just right. In principle, there could be more members of that struct, but in practice, implementations that want to be interoperable will not require you to set any other members. Most don't have other members at all.
Do note, however, that just because connect() receives the address structure via a pointer does not mean you need to use dynamic allocation. It would be a bit more idiomatic to do this:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in srvraddr = { 0 };
srvraddr.sin_family = AF_INET;
srvraddr.sin_port = htons(PORT_A);
srvraddr.sin_addr.s_addr = var;
connect(sockfd, (struct sockaddr *) &srvraddr, sizeof(srvraddr));
Among other things, that saves you having to free the memory afterward.
Whatever I try to do connect always returns me -1. Using perror I get the following error: Connection refused.
As far as I can see, the code you've presented is fine. You may want to check how you are obtaining the in_addr_t value in the first place, and to verify the port number you are using. On the other hand, do not overlook the possibility that the problem is at the remote host: perhaps the port you are trying to connect to is just not open (to you).
This is my way of using connect() to get a connection to "example.com" on port 80:
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
int main(void)
{
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
fprintf(stderr, "socket");
return 0;
}
char domain[] = "example.com";
struct hostent *he;
he = gethostbyname (domain);
if (!he)
{
switch (h_errno)
{
case HOST_NOT_FOUND:
fputs ("The host was not found.\n", stderr);
break;
case NO_ADDRESS:
fputs ("The name is valid but it has no address.\n", stderr);
break;
case NO_RECOVERY:
fputs ("A non-recoverable name server error occurred.\n", stderr);
break;
case TRY_AGAIN:
fputs ("The name server is temporarily unavailable.", stderr);
break;
}
return 1;
}
if (he->h_length < 4)
return 1;
struct sockaddr_in srvraddr;
srvraddr.sin_len = sizeof(srvraddr);
srvraddr.sin_family = AF_INET;
srvraddr.sin_port = htons(80);
srvraddr.sin_addr = * (struct in_addr *) he->h_addr_list[0];
if (connect(sockfd, (struct sockaddr*)&srvraddr, srvraddr.sin_len) == -1) {
fprintf(stderr,"connect() failed\n");
return 1;
}
// Use conection here...
close(sockfd);
return 0;
}
I'm new in sockets and I don't know if its possible to do what I'm trying. First of all, I've looked for more info in Google and in stackoverflow but I haven't found anything :(
Now I explain my problem. I have created client socket (with the functions socket y connect) in the main function with no problem. But then I call a function called sendframe() thet I've created, where I do some stuff and then I use the write function to put a message in the socket. The problem here is that I dont know why the write function gives an error (returns -1). I think the problem is that I haven't passed correctly the socket file descriptor, but I'm not sure (I'm not convinced that using only the file descriptor allows me to write in the socket...)
Here is a snippet of what I'm trying to do:
#include ...
void sendframe(int sockfd);
void main(void) {
//// Open the socket
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("open socket erorr\n");
server = gethostbyname("192.168.20.155");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = 1414;
serv_addr.sin_addr = *((struct in_addr *) server->h_addr);
bzero(&(serv_addr.sin_zero),8);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr))==-1)
error("connect error\n");
exit(-1);
// ..... More code.....
// Send frame
sendframe(&sockfd);
}
void sendframe(int sockfd)
{
// Some stuff...
char *frame
int num = write(sockfd,frame,strlen(frame));
}
Probably the answer is so easy, but I'm new in this. Any clue?
sendframe(&sockfd); should be sendframe(sockfd); as sendframe expects an int, not int *.
I write a little socket programm that only bind to specified ip:port, but bind() failed if the struct sockaddr_in is not bzero and gcc is with option -O2.
Here is the codes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
int main(int argc, char **argv){
struct sockaddr_in addr;
//bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons((unsigned short)9009);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
int sock;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket error");
exit(0);
}
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1){
printf("socket error: %d, %s\n", errno, strerror(errno));
exit(0);
}
return 0;
}
Please notice bzero(&addr, sizeof(addr)); is commented out, I intend to initial the sockadd_in by each member. Compile and run:
$ gcc a.c; ./a.out
OK
$ gcc -O2 a.c; ./a.out
socket error: 49, Can't assign requested address
We can know the struct sockadd_in is defined as:
struct in_addr {
in_addr_t s_addr; /* 32-bit IPv4 address */
/* network byte ordered */
};
struct sockaddr_in {
uint8_t sin_len; /* length of structure (16) */
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* 16-bit TCP or UDP port number */
/* network byte ordered */
struct in_addr sin_addr; /* 32-bit IPv4 address */
/* network byte ordered */
char sin_zero[8]; /* unused */
};
My question is, does the bind() implementation depends on sockaddr_in.sin_zero being cleared?
Edit: Mac OS X, Darwin Kernel Version 12.4.0 X86_64
The rules used in name binding vary between address families. and there's also this sin_zero field in struct sockaddr_in which some people claim must be set to zero. Other people don't claim anything about it (the Linux documentation doesn't even mention it at all), and there are other documentation which claim sin_zero has been removed from struct sockaddr_in,
I have tried with both bzero commented and un-commented. The commented works good some time in a local network but un-commented version works all time either local network or not. so i guess bzeroing is good practice.
I've done socket programming in other languages but never dealt with doing it in C directly. I'm trying to set up a simple server to listen on port 8080 under Windows. I'm using the gcc that comes with mingw to compile the code.
#include <stdio.h>
#include <string.h>
#include <WinSock2.h>
#include <stdint.h>
#include <time.h>
int main(void) {
int s;
int len;
char buffer[1025];
struct sockaddr_in servAddr;
struct sockaddr_in clntAddr;
int clntAddrLen; //length of client socket addre
//Build local (server) socket add
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(8080);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//create socket
if((s=socket(AF_INET, SOCK_STREAM, 0) %lt; 0 )){
perror("Error: Socket Failed!");
printf("%d\n", errno);
exit(1);
}
//bind socket to local address and port
if((bind(s,(struct sockaddr*)&servAddr, sizeof(servAddr)) %lt; 0))
{
perror("Error:bind failed!");
printf("%d\n", errno);
exit(1);
}
for(;;)
{
len = recvfrom(s,buffer, sizeof(buffer),0,(struct sockaddr*)&clntAddr, &clntAddrLen);
//send string
sendto(s, buffer, len, 0, (struct sockaddr*)&clntAddr, sizeof(clntAddr));
}
}
When I run the code it errors out binding but there's no error. This code was taken and slightly modified from this thread: Windows Socket Programming in C
But there's no error code. The output prints that there's no error. It fails at the bind and I'm not sure why. I've been piecing together a few different sources. I literally just want something that can do a hello world/3 way handshake in C on Windows.
Thanks in advance.
This is incorrect due to operator precedence:
if((s=socket(AF_INET, SOCK_STREAM, 0) < 0 )){
as < has higher precedence than =. This means that the code will assign 1 or 0 to s depending on result of socket(AF_INET, SOCK_STREAM, 0) < 0.
Change to:
if((s=socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
Use WSAGetLastError() to obtain failure reason, not errno. From the MSDN bind() reference page:
If no error occurs, bind returns zero. Otherwise, it returns SOCKET_ERROR, and a specific error code can be retrieved by calling WSAGetLastError.
On Windows WSAStartup() must be invoked before any socket functions are called.
Am trying my hand at sockets programming and I need some help because I can't build any of the programs I write. Whenever I try to build any sockets application, the compiler reports the following error:
error: expected specifier-qualifier-list before '_uid32_t'
This variable is inside a struct, which in turn is located in the header file "socket.h", and looks like this:
struct ucred {
pid_t pid;
__uid32_t uid;
__gid32_t gid;
};
There aren't any other errors in the other files and this is the only error the compiler returns.
I don't know if this is of any consequence but the header file is the one that comes with cygwin because the guides and tutorials am using are on Unix sockets and am running Windows XP. Am also using Code::Blocks running a gcc compiler.
I really hope that it's possible to run a program using the Unix sockets API on Windows because I'd really hate to confine myself to winsock only. Also, most of the freely available and comprehensive tutorials on sockets and network programming use Unix sockets.
Here's the code, though I don't think it really matters because I get the exact same error no matter program as long as it's using socket.h.
#include <stdio.h>
#include <string.h>
#include <sys\types.h>
#include <sys\socket.h>
#include <netdb.h>
#include <arpa\inet.h>
int main(int argc, char *argv[])
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
if (argc != 2)
{
fprintf(stderr, "Usage: showip hostname\n");
return 1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;//AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 2;
}
printf("IP addresses for %s:\n\n", argv[1]);
for (p = res; p != NULL; p = p ->ai_next)
{
void *addr;
char *ipver;
//get the pointer to the address itself
//different fields in IPv4 and IPv6:
if (p ->ai_family == AF_INET)
{
//IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p ->ai_addr;
addr = &(ipv4 ->sin_addr);
ipver = "IPv4";
}
else//IPv6
{
struct sockaddr_in *ipv6 = (struct sockaddr_in6 *)p ->ai_addr;
ipver = "IPv6";
}
//convert the IP to a string and print it;
inet_ntop(p ->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
}
freeaddrinfo(res);//free linked list
return 0;
}
There's also other source code from other programs I could have added but I chose this one instead because I got it from the internet and not a textbook so anyone can look it up here.
Try including <unistd.h> and <sys/types.h> before your socket.h.