Last active
July 26, 2023 04:06
-
-
Save mittorn/d7dc8f2a830f086cf74c73a9f65a2206 to your computer and use it in GitHub Desktop.
Static linking helpers. Static-linked glibc tries to load current glibc version dynamically, this is to workaround this mess
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this prevents using glibc's dinamic linker features (which may cause failure) | |
// remove -ldl when linking it, this should remove static linking warning | |
// if you really need dlopen implementation that works in static binary, | |
// try https://github.com/mittorn/custom-linker or android bionic linker | |
void *dlopen( const char *n, int f ) | |
{ | |
return 0; | |
} | |
void *dlsym( void *l, const char *n ) | |
{ | |
return 0; | |
} | |
const char *dlerror() | |
{ | |
return "dlerror"; | |
} | |
int dlclose( void *lib ) | |
{ | |
return 0; | |
} | |
int dladdr(void *addr, void *info) | |
{ | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
simple dns resolver | |
glibc have dns resolver in separate libnss_dns, which does not link staticly | |
btw, other libc implementations usually have hard-coded resolv.conf path, so it will fail if there is no resolv.conf on the target system | |
only getaddrinfo implemented, i'm too lazy to add gethostbyname now | |
linking it should exclude glibc's gettaddrinfo.o and gethstbynm.o and remove static linking warning | |
based on some code found in the internet, orginal author is Silver Moon (m00n.silv3r@gmail.com) 29/4/2009 | |
*/ | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <unistd.h> | |
#define T_A 1 //Ipv4 address | |
//DNS header structure | |
struct DNS_HEADER | |
{ | |
unsigned short id; // identification number | |
unsigned char rd :1; // recursion desired | |
unsigned char tc :1; // truncated message | |
unsigned char aa :1; // authoritive answer | |
unsigned char opcode :4; // purpose of message | |
unsigned char qr :1; // query/response flag | |
unsigned char rcode :4; // response code | |
unsigned char cd :1; // checking disabled | |
unsigned char ad :1; // authenticated data | |
unsigned char z :1; // its z! reserved | |
unsigned char ra :1; // recursion available | |
unsigned short q_count; // number of question entries | |
unsigned short ans_count; // number of answer entries | |
unsigned short auth_count; // number of authority entries | |
unsigned short add_count; // number of resource entries | |
}; | |
//Constant sized fields of query structure | |
struct QUESTION | |
{ | |
unsigned short qtype; | |
unsigned short qclass; | |
}; | |
//Constant sized fields of the resource record structure | |
#pragma pack(push, 1) | |
struct R_DATA | |
{ | |
unsigned short type; | |
unsigned short _class; | |
unsigned int ttl; | |
unsigned short data_len; | |
}; | |
#pragma pack(pop) | |
//Structure of a Query | |
typedef struct | |
{ | |
unsigned char *name; | |
struct QUESTION *ques; | |
} QUERY; | |
/* | |
* This will convert www.google.com to 3www6google3com | |
* got it :) | |
* */ | |
static void ChangetoDnsNameFormat(unsigned char* dns,const char* host) | |
{ | |
int lock = 0 , i, len = strlen( host)+1; | |
//strcat((char*)host,"."); | |
for(i = 0 ; i < len ; i++) | |
{ | |
if(host[i]=='.'|| host[i] == 0) | |
{ | |
*dns++ = i-lock; | |
for(;lock<i;lock++) | |
{ | |
*dns++=host[lock]; | |
} | |
lock++; //or lock=i+1; | |
} | |
} | |
*dns++='\0'; | |
} | |
/* | |
* | |
* */ | |
static int skip_name(unsigned char* reader,unsigned char* buffer) | |
{ | |
unsigned int p=0,jumped=0,offset; | |
int count = 1; | |
while(*reader) | |
{ | |
if(*reader>=192) | |
{ | |
offset = (*reader)*256 + *(reader+1) - 49152; //49152 = 11000000 00000000 ;) | |
reader = buffer + offset - 1; | |
jumped = 1; //we have jumped to another location so counting wont go up! | |
} | |
else p++; | |
reader++; | |
if(jumped==0) count++; | |
} | |
if(jumped==1) count++; | |
return count; | |
} | |
/* | |
* Perform a DNS query by sending a packet | |
* */ | |
static unsigned int dns_lookup(const char *host) | |
{ | |
unsigned char buf[65536],*qname,*reader; | |
int i, s; | |
socklen_t len; | |
//struct sockaddr_in a; | |
//struct RES_RECORD answers[20],auth[20],addit[20]; //the replies from the DNS server | |
struct sockaddr_in dest; | |
struct DNS_HEADER *dns = NULL; | |
struct QUESTION *qinfo = NULL; | |
s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries | |
dest.sin_family = AF_INET; | |
dest.sin_port = htons(53); | |
dest.sin_addr.s_addr = inet_addr("8.8.8.8"); //dns servers | |
//Set the DNS structure to standard queries | |
dns = (struct DNS_HEADER *)&buf; | |
dns->id = (unsigned short) htons(getpid()); | |
dns->qr = 0; //This is a query | |
dns->opcode = 0; //This is a standard query | |
dns->aa = 0; //Not Authoritative | |
dns->tc = 0; //This message is not truncated | |
dns->rd = 1; //Recursion Desired | |
dns->ra = 0; //Recursion not available! hey we dont have it (lol) | |
dns->z = 0; | |
dns->ad = 0; | |
dns->cd = 0; | |
dns->rcode = 0; | |
dns->q_count = htons(1); //we have only 1 question | |
dns->ans_count = 0; | |
dns->auth_count = 0; | |
dns->add_count = 0; | |
//point to the query portion | |
qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)]; | |
ChangetoDnsNameFormat(qname , host); | |
printf("%s %d %d %d %s\n", qname, qname[0], qname[3], qname[7], host); | |
qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen(host) + 2)]; //fill it | |
qinfo->qtype = htons( T_A ); //type of the query , A , MX , CNAME , NS etc | |
qinfo->qclass = htons(1); //its internet (lol) | |
if( sendto(s,(char*)buf,sizeof(struct DNS_HEADER) + (strlen((const char*)host)+2) + sizeof(struct QUESTION),0,(struct sockaddr*)&dest,sizeof(dest)) < 0) | |
perror("sendto failed"); | |
//Receive the answer | |
len = sizeof( dest ); | |
// printf("\nReceiving answer..."); | |
if(recvfrom (s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest , &len ) < 0) | |
perror("recvfrom failed"); | |
dns = (struct DNS_HEADER*) buf; | |
//move ahead of the dns header and the query field | |
reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)host)+2) + sizeof(struct QUESTION)]; | |
for(i=0;i<ntohs(dns->ans_count);i++) | |
{ | |
struct R_DATA *res; | |
//puts(reader); | |
reader += skip_name(reader, buf); | |
res = (struct R_DATA*)(reader); | |
reader += sizeof(struct R_DATA); | |
if(ntohs(res->type) == 1) //if its an ipv4 address | |
{ | |
close(s); | |
// printf("%d\n", reader - buf); | |
return *(unsigned int*)reader; | |
} | |
else reader += skip_name( reader, buf ); | |
} | |
//read authorities | |
for(i=0;i<ntohs(dns->auth_count);i++) | |
{ | |
// puts(reader); | |
reader += skip_name( reader, buf ); | |
reader+=sizeof(struct R_DATA); | |
// puts( reader); | |
reader += skip_name( reader, buf ); | |
} | |
//read additional | |
for(i=0;i<ntohs(dns->add_count);i++) | |
{ | |
struct R_DATA *res; | |
reader += skip_name( reader, buf ); | |
//addit[i].resource | |
res=(struct R_DATA*)(reader); | |
reader+=sizeof(struct R_DATA); | |
if(ntohs(res->type)==1) | |
{ | |
close(s); | |
return *(unsigned int*)reader; | |
} | |
else reader += skip_name( reader, buf ); | |
} | |
close(s); | |
return 0; | |
} | |
char cache_names[256][32]; | |
unsigned int cache_hosts[32]; | |
unsigned char cache_counter; | |
static unsigned int dns_cache(const char *host) | |
{ | |
unsigned int i; | |
for( i = 0; i < 32; i++ ) if(!strcmp( cache_names[i], host ) ) return cache_hosts[i]; | |
i = dns_lookup(host); | |
if( i ) | |
cache_hosts[cache_counter = ((cache_counter + 1) & 31)] = i,strncpy( cache_names[cache_counter], host, 255 ); | |
return i; | |
} | |
static unsigned int lookup4( const char *node ) | |
{ | |
unsigned int address; | |
if( node[0] >= '0' && node[0] <= '9' ) | |
address = inet_addr(node); | |
else | |
address = dns_cache(node); | |
struct sockaddr_in a; | |
a.sin_addr.s_addr=address; | |
printf("%s\n",inet_ntoa(a.sin_addr)); | |
return address; | |
} | |
#include <pthread.h> | |
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; | |
int getaddrinfo(const char *node, const char *service, | |
const struct addrinfo *hints, | |
struct addrinfo **res) | |
{ | |
*res = calloc(sizeof(struct addrinfo), 1); | |
(*res)->ai_family = AF_INET; | |
(*res)->ai_socktype = SOCK_STREAM; | |
(*res)->ai_protocol = IPPROTO_TCP; | |
(*res)->ai_addrlen = sizeof(struct sockaddr_in); | |
(*res)->ai_addr = malloc((*res)->ai_addrlen); | |
pthread_mutex_lock( &lock ); | |
*(int *)&((struct sockaddr_in *)(*res)->ai_addr)->sin_addr = lookup4( node ); | |
pthread_mutex_unlock( &lock ); | |
((struct sockaddr_in *)(*res)->ai_addr)->sin_port = htons(443); | |
((struct sockaddr_in *)(*res)->ai_addr)->sin_family = AF_INET; | |
return 0; | |
} | |
void freeaddrinfo(struct addrinfo *res) | |
{ | |
free(res->ai_addr); | |
free(res); | |
} | |
struct hostent *gethostbyname(const char *name) { return 0; } | |
#ifdef RES_TEST | |
int main( int argc, char** argv ) | |
{ | |
return lookup4(argv[1]) != 0; | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this prevents glib from using glibc's dinamic linker features (which may cause failure) | |
void *g_get_prgname(){return NULL;} | |
void g_set_prgname(void *n){} | |
void *g_get_tmp_dir(){return NULL;} // The return value is never NULL or the empty string. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment