1
0
mirror of https://github.com/rofl0r/proxychains-ng synced 2026-05-14 17:42:36 +08:00

Compare commits

..

29 Commits

11 changed files with 237 additions and 74 deletions
+1
View File
@@ -1,4 +1,5 @@
proxychains4 proxychains4
proxychains4-daemon
*.bz2 *.bz2
*.xz *.xz
*.o *.o
+12 -6
View File
@@ -11,7 +11,8 @@ bindir = $(exec_prefix)/bin
prefix = /usr/local/ prefix = /usr/local/
includedir = $(prefix)/include includedir = $(prefix)/include
libdir = $(prefix)/lib libdir = $(prefix)/lib
sysconfdir=$(prefix)/etc sysconfdir = $(prefix)/etc
zshcompletiondir = $(prefix)/share/zsh/site-functions
OBJS = src/common.o src/main.o OBJS = src/common.o src/main.o
@@ -48,6 +49,7 @@ PXCHAINS = proxychains4
PXCHAINS_D = proxychains4-daemon PXCHAINS_D = proxychains4-daemon
ALL_TOOLS = $(PXCHAINS) $(PXCHAINS_D) ALL_TOOLS = $(PXCHAINS) $(PXCHAINS_D)
ALL_CONFIGS = src/proxychains.conf ALL_CONFIGS = src/proxychains.conf
ZSH_COMPLETION = completions/zsh/_proxychains4
-include config.mak -include config.mak
@@ -68,9 +70,13 @@ $(DESTDIR)$(libdir)/%: %
$(DESTDIR)$(sysconfdir)/%: src/% $(DESTDIR)$(sysconfdir)/%: src/%
$(INSTALL) -D -m 644 $< $@ $(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(zshcompletiondir)/%: completions/zsh/%
$(INSTALL) -D -m 644 $< $@
install-libs: $(ALL_LIBS:%=$(DESTDIR)$(libdir)/%) install-libs: $(ALL_LIBS:%=$(DESTDIR)$(libdir)/%)
install-tools: $(ALL_TOOLS:%=$(DESTDIR)$(bindir)/%) install-tools: $(ALL_TOOLS:%=$(DESTDIR)$(bindir)/%)
install-config: $(ALL_CONFIGS:src/%=$(DESTDIR)$(sysconfdir)/%) install-config: $(ALL_CONFIGS:src/%=$(DESTDIR)$(sysconfdir)/%)
install-zsh-completion: $(ZSH_COMPLETION:completions/zsh/%=$(DESTDIR)$(zshcompletiondir)/%)
clean: clean:
rm -f $(ALL_LIBS) rm -f $(ALL_LIBS)
@@ -87,14 +93,14 @@ src/version.o: src/version.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_MAIN) $(INC) $(PIC) -c -o $@ $< $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_MAIN) $(INC) $(PIC) -c -o $@ $<
$(LDSO_PATHNAME): $(LOBJS) $(LDSO_PATHNAME): $(LOBJS)
$(CC) $(LDFLAGS) $(LD_SET_SONAME)$(LDSO_PATHNAME) $(USER_LDFLAGS) \ $(CC) $(LDFLAGS) $(FAT_LDFLAGS) $(LD_SET_SONAME)$(LDSO_PATHNAME) \
-shared -o $@ $^ $(SOCKET_LIBS) $(USER_LDFLAGS) -shared -o $@ $^ $(SOCKET_LIBS)
$(PXCHAINS): $(OBJS) $(PXCHAINS): $(OBJS)
$(CC) $^ $(USER_LDFLAGS) $(LIBDL) -o $@ $(CC) $^ $(FAT_BIN_LDFLAGS) $(USER_LDFLAGS) $(LIBDL) -o $@
$(PXCHAINS_D): $(DOBJS) $(PXCHAINS_D): $(DOBJS)
$(CC) $^ $(USER_LDFLAGS) -o $@ $(CC) $^ $(FAT_BIN_LDFLAGS) $(USER_LDFLAGS) -o $@
.PHONY: all clean install install-config install-libs install-tools .PHONY: all clean install install-config install-libs install-tools install-zsh-completion
+19 -1
View File
@@ -1,4 +1,4 @@
ProxyChains-NG ver 4.16 README ProxyChains-NG ver 4.17 README
============================= =============================
ProxyChains is a UNIX program, that hooks network-related libc functions ProxyChains is a UNIX program, that hooks network-related libc functions
@@ -52,6 +52,15 @@ ProxyChains-NG ver 4.16 README
Changelog: Changelog:
---------- ----------
Version 4.17
- add hook for close_range function, fixing newer versions of openssh
- fat-binary-m1 option for mac
- fix DNS error handling in proxy_dns_old
- simplify init code
- fix openbsd preloading
- fix double-close in multithreaded apps
- various improvements to configure script
Version 4.16 Version 4.16
- fix regression in configure script linker flag detection - fix regression in configure script linker flag detection
- remove 10 year old workaround for wrong glibc getnameinfo signature - remove 10 year old workaround for wrong glibc getnameinfo signature
@@ -254,6 +263,15 @@ Known Problems:
there are unconfirmed reports that it works as root though. there are unconfirmed reports that it works as root though.
musl libc is unaffected from the bug. musl libc is unaffected from the bug.
Useful links
------------
the following sites may prove useful to check for leaks:
https://ipfighter.com/
https://browserleaks.com/webrtc
https://dnsleaktest.com
http://check.torproject.org - tor specific
http://ifconfig.me - can be used via curl
http://ifconfig.io/
Community: Community:
---------- ----------
+1 -1
View File
@@ -1 +1 @@
4.16 4.17
+8
View File
@@ -0,0 +1,8 @@
#compdef proxychains4
_arguments \
'(- : *)--help[More help in README file]' \
'-q[makes proxychains quiet - this overrides the config setting]' \
'-f[allows one to manually specify a configfile to use]: :_files' \
'(-)1: :{_command_names -e}' \
'*:: :_normal'
Vendored
+44 -2
View File
@@ -86,6 +86,8 @@ usage() {
echo " if set to yes ignores CVE-2015-3887 and makes it possible" echo " if set to yes ignores CVE-2015-3887 and makes it possible"
echo " to preload from current dir (possibly insecure, but handy)" echo " to preload from current dir (possibly insecure, but handy)"
echo "--fat-binary : build for both i386 and x86_64 architectures on 64-bit Macs" echo "--fat-binary : build for both i386 and x86_64 architectures on 64-bit Macs"
echo "--fat-binary-m1 : build for both arm64e and x86_64 architectures on M1 Macs"
echo "--fat-binary-m2 : build for arm64, arm64e and x86_64 architectures on M2+ Macs"
echo "--hookmethod=dlsym|dyld hook method for osx. default: auto" echo "--hookmethod=dlsym|dyld hook method for osx. default: auto"
echo " if OSX >= 12 is detected, dyld method will be used if auto." echo " if OSX >= 12 is detected, dyld method will be used if auto."
echo "--help : show this text" echo "--help : show this text"
@@ -100,6 +102,8 @@ spliteq() {
} }
fat_binary= fat_binary=
fat_binary_m1=
fat_binary_m2=
ignore_cve=no ignore_cve=no
hookmethod=auto hookmethod=auto
@@ -115,6 +119,8 @@ parsearg() {
--ignore-cve=*) ignore_cve=`spliteq $1`;; --ignore-cve=*) ignore_cve=`spliteq $1`;;
--hookmethod=*) hookmethod=`spliteq $1`;; --hookmethod=*) hookmethod=`spliteq $1`;;
--fat-binary) fat_binary=1;; --fat-binary) fat_binary=1;;
--fat-binary-m1) fat_binary_m1=1;;
--fat-binary-m2) fat_binary_m2=1;;
--help) usage;; --help) usage;;
esac esac
} }
@@ -174,6 +180,25 @@ ishaiku() {
} }
check_compile 'whether C compiler works' '' 'int main() {return 0;}' || fail 'error: install a C compiler and library' check_compile 'whether C compiler works' '' 'int main() {return 0;}' || fail 'error: install a C compiler and library'
check_compile 'whether libc headers are complete' '' '#include <netdb.h>\nint main() {return 0;}' || fail 'error: necessary libc headers are not installed'
check_compile 'whether C compiler understands -Wno-unknown-pragmas' '-Wno-unknown-pragmas' 'int main() {return 0;}'
check_compile 'whether C compiler understands -Werror=implicit-function-declaration' '-Werror=implicit-function-declaration' 'int main() {return 0;}'
if ! check_compile 'whether getnameinfo() servlen argument is POSIX compliant (socklen_t)' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=socklen_t -DGN_FLAGS_T=int" \
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);int main() {\nreturn 0;}' ; then
# GLIBC < 2.14
if ! check_compile 'whether getnameinfo() flags argument is unsigned' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=socklen_t -DGN_FLAGS_T=unsigned" \
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, unsigned);int main() {\nreturn 0;}' ; then
if ! check_compile 'whether getnameinfo() servlen argument is size_t' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=size_t -DGN_FLAGS_T=int" \
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, size_t, int);int main() {\nreturn 0;}' ; then
# OpenBSD & FreeBSD
if ! check_compile 'whether getnameinfo() servlen and nodelen argument is size_t' "-DGN_NODELEN_T=size_t -DGN_SERVLEN_T=size_t -DGN_FLAGS_T=int" \
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int);int main() {\nreturn 0;}' ; then
fail "failed to detect getnameinfo signature"
fi
fi
fi
fi
check_compile 'whether we have GNU-style getservbyname_r()' "-DHAVE_GNU_GETSERVBYNAME_R" \ check_compile 'whether we have GNU-style getservbyname_r()' "-DHAVE_GNU_GETSERVBYNAME_R" \
'#define _GNU_SOURCE\n#include <netdb.h>\nint main() {\nstruct servent *se = 0;struct servent se_buf;char buf[1024];\ngetservbyname_r("foo", (void*) 0, &se_buf, buf, sizeof(buf), &se);\nreturn 0;}' '#define _GNU_SOURCE\n#include <netdb.h>\nint main() {\nstruct servent *se = 0;struct servent se_buf;char buf[1024];\ngetservbyname_r("foo", (void*) 0, &se_buf, buf, sizeof(buf), &se);\nreturn 0;}'
@@ -196,6 +221,7 @@ check_define __APPLE__ && {
fi fi
} }
check_define __FreeBSD__ && bsd_detected=true check_define __FreeBSD__ && bsd_detected=true
check_define __NetBSD__ && bsd_detected=true
check_define __OpenBSD__ && { check_define __OpenBSD__ && {
bsd_detected=true bsd_detected=true
echo "CFLAGS+=-DIS_OPENBSD">>config.mak echo "CFLAGS+=-DIS_OPENBSD">>config.mak
@@ -225,7 +251,7 @@ check_link "whether we can use -Wl,--no-as-needed" "-Wl,--no-as-needed" \
LD_SONAME_FLAG= LD_SONAME_FLAG=
printf "checking what's the option to use in linker to set library name ... " printf "checking what's the option to use in linker to set library name ... "
for o in --soname -h -soname -install_name; do for o in --soname -h -soname -install_name; do
check_link_silent "-shared -Wl,$o,libconftest.so" "void test_func(int a) {}" && LD_SONAME_FLAG=$o && break check_link_silent "-shared -Wl,$o,libconftest.so" "void test_func(void) {}" && LD_SONAME_FLAG=$o && break
done done
if [ -z "$LD_SONAME_FLAG" ]; then if [ -z "$LD_SONAME_FLAG" ]; then
printf '\ncannot find an option to set library name\n' printf '\ncannot find an option to set library name\n'
@@ -259,7 +285,20 @@ if ismac ; then
if ismac64 && [ "$fat_binary" = 1 ] ; then if ismac64 && [ "$fat_binary" = 1 ] ; then
echo "Configuring a fat binary for i386 and x86_64" echo "Configuring a fat binary for i386 and x86_64"
echo "MAC_CFLAGS+=-arch i386 -arch x86_64">>config.mak echo "MAC_CFLAGS+=-arch i386 -arch x86_64">>config.mak
echo "LDFLAGS+=-arch i386 -arch x86_64">>config.mak echo "FAT_LDFLAGS=-arch i386 -arch x86_64">>config.mak
echo "FAT_BIN_LDFLAGS=-arch i386 -arch x86_64">>config.mak
fi
if [ "$fat_binary_m1" = 1 ] ; then
echo "Configuring a fat binary for arm64[e] and x86_64"
echo "MAC_CFLAGS+=-arch arm64 -arch arm64e -arch x86_64">>config.mak
echo "FAT_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak
echo "FAT_BIN_LDFLAGS=-arch arm64 -arch x86_64">>config.mak
fi
if [ "$fat_binary_m2" = 1 ] ; then
echo "Configuring a fat binary for arm64[e] and x86_64"
echo "MAC_CFLAGS+=-arch arm64 -arch arm64e -arch x86_64">>config.mak
echo "FAT_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak
echo "FAT_BIN_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak
fi fi
elif isbsd ; then elif isbsd ; then
echo LIBDL=>>config.mak echo LIBDL=>>config.mak
@@ -274,3 +313,6 @@ elif ishaiku ; then
fi fi
echo "Done, now run $make_cmd && $make_cmd install" echo "Done, now run $make_cmd && $make_cmd install"
if [ "$fat_binary_m2" = 1 ] ; then
echo "Don't forget to run csrutil disable and sudo nvram boot-args=-arm64e_preview_abi"
fi
+33 -34
View File
@@ -462,8 +462,10 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
error1: error1:
proxychains_write_log(TP " timeout\n"); proxychains_write_log(TP " timeout\n");
error: error:
if(*fd != -1) if(*fd != -1) {
close(*fd); close(*fd);
*fd = -1;
}
return SOCKET_ERROR; return SOCKET_ERROR;
} }
@@ -520,9 +522,9 @@ static unsigned int calc_alive(proxy_data * pd, unsigned int proxy_count) {
} }
static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) { static int chain_step(int *ns, proxy_data * pfrom, proxy_data * pto) {
int retcode = -1; int retcode = -1;
char *hostname; char *hostname, *errmsg = 0;
char hostname_buf[MSG_LEN_MAX]; char hostname_buf[MSG_LEN_MAX];
char ip_buf[INET6_ADDRSTRLEN]; char ip_buf[INET6_ADDRSTRLEN];
int v6 = pto->ip.is_v6; int v6 = pto->ip.is_v6;
@@ -536,31 +538,34 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
usenumericip: usenumericip:
if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) { if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) {
pto->ps = DOWN_STATE; pto->ps = DOWN_STATE;
proxychains_write_log("<--ip conversion error!\n"); errmsg = "<--ip conversion error!\n";
close(ns); retcode = SOCKET_ERROR;
return SOCKET_ERROR; goto err;
} }
hostname = ip_buf; hostname = ip_buf;
} }
proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port)); proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port));
retcode = tunnel_to(ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass); retcode = tunnel_to(*ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
switch (retcode) { switch (retcode) {
case SUCCESS: case SUCCESS:
pto->ps = BUSY_STATE; pto->ps = BUSY_STATE;
break; break;
case BLOCKED: case BLOCKED:
pto->ps = BLOCKED_STATE; pto->ps = BLOCKED_STATE;
proxychains_write_log("<--denied\n"); errmsg = "<--denied\n";
close(ns); goto err;
break;
case SOCKET_ERROR: case SOCKET_ERROR:
pto->ps = DOWN_STATE; pto->ps = DOWN_STATE;
proxychains_write_log("<--socket error or timeout!\n"); errmsg = "<--socket error or timeout!\n";
close(ns); goto err;
break;
} }
return retcode; return retcode;
err:
if(errmsg) proxychains_write_log(errmsg);
if(*ns != -1) close(*ns);
*ns = -1;
return retcode;
} }
int connect_proxy_chain(int sock, ip_type target_ip, int connect_proxy_chain(int sock, ip_type target_ip,
@@ -596,7 +601,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
p2 = select_proxy(FIFOLY, pd, proxy_count, &offset); p2 = select_proxy(FIFOLY, pd, proxy_count, &offset);
if(!p2) if(!p2)
break; break;
if(SUCCESS != chain_step(ns, p1, p2)) { if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("GOTO AGAIN 1\n"); PDEBUG("GOTO AGAIN 1\n");
goto again; goto again;
} }
@@ -605,7 +610,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
break; break;
@@ -643,7 +648,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
/* Try from the beginning to where we started */ /* Try from the beginning to where we started */
offset = 0; offset = 0;
continue; continue;
} else if(SUCCESS != chain_step(ns, p1, p2)) { } else if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("GOTO AGAIN 1\n"); PDEBUG("GOTO AGAIN 1\n");
goto again; goto again;
} else } else
@@ -655,7 +660,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
p3->port = target_port; p3->port = target_port;
proxychains_proxy_offset = offset+1; proxychains_proxy_offset = offset+1;
PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len); PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len);
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
break; break;
@@ -673,7 +678,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
while(offset < proxy_count) { while(offset < proxy_count) {
if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset))) if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset)))
break; break;
if(SUCCESS != chain_step(ns, p1, p2)) { if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("chain_step failed\n"); PDEBUG("chain_step failed\n");
goto error_strict; goto error_strict;
} }
@@ -682,7 +687,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
break; break;
@@ -698,7 +703,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
while(++curr_len < max_chain) { while(++curr_len < max_chain) {
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset))) if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
goto error_more; goto error_more;
if(SUCCESS != chain_step(ns, p1, p2)) { if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("GOTO AGAIN 2\n"); PDEBUG("GOTO AGAIN 2\n");
goto again; goto again;
} }
@@ -707,7 +712,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
} }
@@ -824,7 +829,8 @@ struct hostent* proxy_gethostbyname_old(const char *name)
close(pipe_fd[0]); close(pipe_fd[0]);
got_buff: got_buff:
l = strlen(buff); l = strlen(buff);
if(l && buff[l-1] == '\n') buff[l-1] = 0; if (!l) goto err_dns;
if (buff[l-1] == '\n') buff[l-1] = 0;
addr = inet_addr(buff); addr = inet_addr(buff);
if (addr == (in_addr_t) (-1)) if (addr == (in_addr_t) (-1))
goto err_dns; goto err_dns;
@@ -839,8 +845,7 @@ got_buff:
name, inet_ntoa(*(struct in_addr*)&addr)); name, inet_ntoa(*(struct in_addr*)&addr));
return &hostent_space; return &hostent_space;
err_dns: err_dns:
proxychains_write_log("|DNS-response|: %s does not exist\n", name); proxychains_write_log("|DNS-response|: %s lookup error\n", name);
perror("err_dns");
err: err:
return NULL; return NULL;
} }
@@ -969,12 +974,13 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
node?node:"",service?service:"",hints?(int)hints->ai_flags:0); node?node:"",service?service:"",hints?(int)hints->ai_flags:0);
space = calloc(1, sizeof(struct addrinfo_data)); space = calloc(1, sizeof(struct addrinfo_data));
if(!space) goto err1; if(!space) return EAI_MEMORY;
if(node && !my_inet_aton(node, space)) { if(node && !my_inet_aton(node, space)) {
/* some folks (nmap) use getaddrinfo() with AI_NUMERICHOST to check whether a string /* some folks (nmap) use getaddrinfo() with AI_NUMERICHOST to check whether a string
containing a numeric ip was passed. we must return failure in that case. */ containing a numeric ip was passed. we must return failure in that case. */
if(hints && (hints->ai_flags & AI_NUMERICHOST)) { if(hints && (hints->ai_flags & AI_NUMERICHOST)) {
err_nn:
free(space); free(space);
return EAI_NONAME; return EAI_NONAME;
} }
@@ -987,13 +993,13 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr, memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr,
*(hp->h_addr_list), sizeof(in_addr_t)); *(hp->h_addr_list), sizeof(in_addr_t));
else else
goto err2; goto err_nn;
} else if(node) { } else if(node) {
af = ((struct sockaddr_in *) &space->sockaddr_space)->sin_family; af = ((struct sockaddr_in *) &space->sockaddr_space)->sin_family;
} else if(!node && !(hints->ai_flags & AI_PASSIVE)) { } else if(!node && !(hints->ai_flags & AI_PASSIVE)) {
af = ((struct sockaddr_in *) &space->sockaddr_space)->sin_family = AF_INET; af = ((struct sockaddr_in *) &space->sockaddr_space)->sin_family = AF_INET;
memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr, memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr,
(char[]){127,0,0,1}, 4); "\177\0\0\1", 4);
} }
if(service) mygetservbyname_r(service, NULL, &se_buf, buf, sizeof(buf), &se); if(service) mygetservbyname_r(service, NULL, &se_buf, buf, sizeof(buf), &se);
@@ -1026,12 +1032,5 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
#endif #endif
p->ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); p->ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
} }
goto out;
err2:
free(space);
err1:
return 1;
out:
return 0; return 0;
} }
+3 -2
View File
@@ -100,16 +100,17 @@ int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port
void proxychains_write_log(char *str, ...); void proxychains_write_log(char *str, ...);
typedef int (*close_t)(int); typedef int (*close_t)(int);
typedef int (*close_range_t)(unsigned, unsigned, int);
typedef int (*connect_t)(int, const struct sockaddr *, socklen_t); typedef int (*connect_t)(int, const struct sockaddr *, socklen_t);
typedef struct hostent* (*gethostbyname_t)(const char *); typedef struct hostent* (*gethostbyname_t)(const char *);
typedef int (*freeaddrinfo_t)(struct addrinfo *); typedef void (*freeaddrinfo_t)(struct addrinfo *);
typedef struct hostent *(*gethostbyaddr_t) (const void *, socklen_t, int); typedef struct hostent *(*gethostbyaddr_t) (const void *, socklen_t, int);
typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *, typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *,
struct addrinfo **); struct addrinfo **);
typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *, typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *,
socklen_t, char *, socklen_t, int); GN_NODELEN_T, char *, GN_SERVLEN_T, GN_FLAGS_T);
typedef ssize_t (*sendto_t) (int sockfd, const void *buf, size_t len, int flags, typedef ssize_t (*sendto_t) (int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen); const struct sockaddr *dest_addr, socklen_t addrlen);
+1
View File
@@ -5,6 +5,7 @@
*/ */
#undef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#include <unistd.h> #include <unistd.h>
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
+106 -23
View File
@@ -56,6 +56,7 @@ connect_t true___xnet_connect;
#endif #endif
close_t true_close; close_t true_close;
close_range_t true_close_range;
connect_t true_connect; connect_t true_connect;
gethostbyname_t true_gethostbyname; gethostbyname_t true_gethostbyname;
getaddrinfo_t true_getaddrinfo; getaddrinfo_t true_getaddrinfo;
@@ -86,13 +87,14 @@ static int init_l = 0;
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct); static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
static void* load_sym(char* symname, void* proxyfunc) { static void* load_sym(char* symname, void* proxyfunc, int is_mandatory) {
void *funcptr = dlsym(RTLD_NEXT, symname); void *funcptr = dlsym(RTLD_NEXT, symname);
if(!funcptr) { if(is_mandatory && !funcptr) {
fprintf(stderr, "Cannot load symbol '%s' %s\n", symname, dlerror()); fprintf(stderr, "Cannot load symbol '%s' %s\n", symname, dlerror());
exit(1); exit(1);
} else if (!funcptr) {
return funcptr;
} else { } else {
PDEBUG("loaded symbol '%s'" " real addr %p wrapped addr %p\n", symname, funcptr, proxyfunc); PDEBUG("loaded symbol '%s'" " real addr %p wrapped addr %p\n", symname, funcptr, proxyfunc);
} }
@@ -103,17 +105,22 @@ static void* load_sym(char* symname, void* proxyfunc) {
return funcptr; return funcptr;
} }
#define INIT() init_lib_wrapper(__FUNCTION__)
#include "allocator_thread.h" #include "allocator_thread.h"
const char *proxychains_get_version(void); const char *proxychains_get_version(void);
static void setup_hooks(void); static void setup_hooks(void);
typedef struct {
unsigned int first, last, flags;
} close_range_args_t;
/* If there is some `close` or `close_range` system call before do_init,
we buffer it, and actually execute them in do_init. */
static int close_fds[16]; static int close_fds[16];
static int close_fds_cnt = 0; static int close_fds_cnt = 0;
static close_range_args_t close_range_buffer[16];
static int close_range_buffer_cnt = 0;
static unsigned get_rand_seed(void) { static unsigned get_rand_seed(void) {
#ifdef HAVE_CLOCK_GETTIME #ifdef HAVE_CLOCK_GETTIME
@@ -126,18 +133,28 @@ static unsigned get_rand_seed(void) {
} }
static void do_init(void) { static void do_init(void) {
char *env;
srand(get_rand_seed()); srand(get_rand_seed());
core_initialize(); core_initialize();
/* read the config file */ env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR);
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct); if(env && *env == '1')
DUMP_PROXY_CHAIN(proxychains_pd, proxychains_proxy_count); proxychains_quiet_mode = 1;
proxychains_write_log(LOG_PREFIX "DLL init: proxychains-ng %s\n", proxychains_get_version()); proxychains_write_log(LOG_PREFIX "DLL init: proxychains-ng %s\n", proxychains_get_version());
setup_hooks(); setup_hooks();
/* read the config file */
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
DUMP_PROXY_CHAIN(proxychains_pd, proxychains_proxy_count);
while(close_fds_cnt) true_close(close_fds[--close_fds_cnt]); while(close_fds_cnt) true_close(close_fds[--close_fds_cnt]);
while(close_range_buffer_cnt) {
int i = --close_range_buffer_cnt;
true_close_range(close_range_buffer[i].first, close_range_buffer[i].last, close_range_buffer[i].flags);
}
init_l = 1; init_l = 1;
rdns_init(proxychains_resolver); rdns_init(proxychains_resolver);
@@ -151,16 +168,19 @@ static void init_lib_wrapper(const char* caller) {
pthread_once(&init_once, do_init); pthread_once(&init_once, do_init);
} }
/* if we use gcc >= 3, we can instruct the dynamic loader /* if we use gcc >= 3, we can instruct the dynamic loader
* to call init_lib at link time. otherwise it gets loaded * to call init_lib at link time. otherwise it gets loaded
* lazily, which has the disadvantage that there's a potential * lazily, which has the disadvantage that there's a potential
* race condition if 2 threads call it before init_l is set * race condition if 2 threads call it before init_l is set
* and PTHREAD support was disabled */ * and PTHREAD support was disabled */
#if __GNUC__ > 2 #if __GNUC__+0 > 2
__attribute__((constructor)) __attribute__((constructor))
static void gcc_init(void) { static void gcc_init(void) {
INIT(); init_lib_wrapper(__FUNCTION__);
} }
#define INIT() do {} while(0)
#else
#define INIT() init_lib_wrapper(__FUNCTION__)
#endif #endif
@@ -221,7 +241,7 @@ static int proxy_from_string(const char *proxystring,
ul = p-u; ul = p-u;
p++; p++;
pl = at-p; pl = at-p;
if(proxytype == RS_PT_SOCKS5 && (ul > 255 || pl > 255)) if(ul > 255 || pl > 255)
return 0; return 0;
memcpy(user_buf, u, ul); memcpy(user_buf, u, ul);
user_buf[ul]=0; user_buf[ul]=0;
@@ -293,10 +313,6 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
exit(1); exit(1);
} }
env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR);
if(env && *env == '1')
proxychains_quiet_mode = 1;
while(fgets(buf, sizeof(buf), file)) { while(fgets(buf, sizeof(buf), file)) {
buff = buf; buff = buf;
/* remove leading whitespace */ /* remove leading whitespace */
@@ -335,7 +351,7 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
if(*ct == STRICT_TYPE && proxychains_resolver >= DNSLF_RDNS_START && count > 0) { if(*ct == STRICT_TYPE && proxychains_resolver >= DNSLF_RDNS_START && count > 0) {
/* we can allow dns hostnames for all but the first proxy in the list if chaintype is strict, as remote lookup can be done */ /* we can allow dns hostnames for all but the first proxy in the list if chaintype is strict, as remote lookup can be done */
rdns_init(proxychains_resolver); rdns_init(proxychains_resolver);
ip_type4 internal_ip = at_get_ip_for_host(host, strlen(host)); ip_type4 internal_ip = rdns_get_ip_for_host(host, strlen(host));
pd[count].ip.is_v6 = 0; pd[count].ip.is_v6 = 0;
host_ip->addr.v4 = internal_ip; host_ip->addr.v4 = internal_ip;
if(internal_ip.as_int == IPT4_INVALID.as_int) if(internal_ip.as_int == IPT4_INVALID.as_int)
@@ -587,6 +603,69 @@ static int is_v4inv6(const struct in6_addr *a) {
return !memcmp(a->s6_addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); return !memcmp(a->s6_addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
} }
static void intsort(int *a, int n) {
int i, j, s;
for(i=0; i<n; ++i)
for(j=i+1; j<n; ++j)
if(a[j] < a[i]) {
s = a[i];
a[i] = a[j];
a[j] = s;
}
}
/* Warning: Linux manual says the third arg is `unsigned int`, but unistd.h says `int`. */
HOOKFUNC(int, close_range, unsigned first, unsigned last, int flags) {
if(true_close_range == NULL) {
fprintf(stderr, "Calling close_range, but this platform does not provide this system call. ");
return -1;
}
if(!init_l) {
/* push back to cache, and delay the execution. */
if(close_range_buffer_cnt >= (sizeof close_range_buffer / sizeof close_range_buffer[0])) {
errno = ENOMEM;
return -1;
}
int i = close_range_buffer_cnt++;
close_range_buffer[i].first = first;
close_range_buffer[i].last = last;
close_range_buffer[i].flags = flags;
return errno = 0;
}
if(proxychains_resolver != DNSLF_RDNS_THREAD) return true_close_range(first, last, flags);
/* prevent rude programs (like ssh) from closing our pipes */
int res = 0, uerrno = 0, i;
int protected_fds[] = {req_pipefd[0], req_pipefd[1], resp_pipefd[0], resp_pipefd[1]};
intsort(protected_fds, 4);
/* We are skipping protected_fds while calling true_close_range()
* If protected_fds cut the range into some sub-ranges, we close sub-ranges BEFORE cut point in the loop.
* [first, cut1-1] , [cut1+1, cut2-1] , [cut2+1, cut3-1]
* Finally, we delete the remaining sub-range, outside the loop. [cut3+1, tail]
*/
int next_fd_to_close = first;
for(i = 0; i < 4; ++i) {
if(protected_fds[i] < first || protected_fds[i] > last)
continue;
int prev = (i == 0 || protected_fds[i-1] < first) ? first : protected_fds[i-1]+1;
if(prev != protected_fds[i]) {
if(-1 == true_close_range(prev, protected_fds[i]-1, flags)) {
res = -1;
uerrno = errno;
}
}
next_fd_to_close = protected_fds[i]+1;
}
if(next_fd_to_close <= last) {
if(-1 == true_close_range(next_fd_to_close, last, flags)) {
res = -1;
uerrno = errno;
}
}
errno = uerrno;
return res;
}
HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) { HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) {
INIT(); INIT();
PFUNC(); PFUNC();
@@ -688,7 +767,7 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len)
} }
#ifdef IS_SOLARIS #ifdef IS_SOLARIS
HOOKFUNC(int, __xnet_connect, int sock, const struct sockaddr *addr, unsigned int len) HOOKFUNC(int, __xnet_connect, int sock, const struct sockaddr *addr, unsigned int len) {
return connect(sock, addr, len); return connect(sock, addr, len);
} }
#endif #endif
@@ -729,8 +808,8 @@ HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
} }
HOOKFUNC(int, getnameinfo, const struct sockaddr *sa, socklen_t salen, HOOKFUNC(int, getnameinfo, const struct sockaddr *sa, socklen_t salen,
char *host, socklen_t hostlen, char *serv, char *host, GN_NODELEN_T hostlen, char *serv,
socklen_t servlen, int flags) GN_SERVLEN_T servlen, GN_FLAGS_T flags)
{ {
INIT(); INIT();
PFUNC(); PFUNC();
@@ -825,8 +904,11 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
#ifdef MONTEREY_HOOKING #ifdef MONTEREY_HOOKING
#define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = &X; } while(0) #define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = &X; } while(0)
#define SETUP_SYM_OPTIONAL(X)
#else #else
#define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = load_sym( # X, X ); } while(0) #define SETUP_SYM_IMPL(X, IS_MANDATORY) do { if (! true_ ## X ) true_ ## X = load_sym( # X, X, IS_MANDATORY ); } while(0)
#define SETUP_SYM(X) SETUP_SYM_IMPL(X, 1)
#define SETUP_SYM_OPTIONAL(X) SETUP_SYM_IMPL(X, 0)
#endif #endif
static void setup_hooks(void) { static void setup_hooks(void) {
@@ -841,6 +923,7 @@ static void setup_hooks(void) {
SETUP_SYM(__xnet_connect); SETUP_SYM(__xnet_connect);
#endif #endif
SETUP_SYM(close); SETUP_SYM(close);
SETUP_SYM_OPTIONAL(close_range);
} }
#ifdef MONTEREY_HOOKING #ifdef MONTEREY_HOOKING
+9 -5
View File
@@ -135,16 +135,20 @@ int main(int argc, char *argv[]) {
if(!quiet) if(!quiet)
fprintf(stderr, LOG_PREFIX "preloading %s/%s\n", prefix, dll_name); fprintf(stderr, LOG_PREFIX "preloading %s/%s\n", prefix, dll_name);
#if defined(IS_MAC) || defined(IS_OPENBSD)
#define LD_PRELOAD_SEP ":"
#else
/* Dynlinkers for Linux and most BSDs seem to support space
as LD_PRELOAD separator, with colon added only recently.
We use the old syntax for maximum compat */
#define LD_PRELOAD_SEP " "
#endif
#ifdef IS_MAC #ifdef IS_MAC
putenv("DYLD_FORCE_FLAT_NAMESPACE=1"); putenv("DYLD_FORCE_FLAT_NAMESPACE=1");
#define LD_PRELOAD_ENV "DYLD_INSERT_LIBRARIES" #define LD_PRELOAD_ENV "DYLD_INSERT_LIBRARIES"
#define LD_PRELOAD_SEP ":"
#else #else
#define LD_PRELOAD_ENV "LD_PRELOAD" #define LD_PRELOAD_ENV "LD_PRELOAD"
/* all historic implementations of BSD and linux dynlinkers seem to support
space as LD_PRELOAD separator, with colon added only recently.
we use the old syntax for maximum compat */
#define LD_PRELOAD_SEP " "
#endif #endif
char *old_val = getenv(LD_PRELOAD_ENV); char *old_val = getenv(LD_PRELOAD_ENV);
snprintf(buf, sizeof(buf), LD_PRELOAD_ENV "=%s/%s%s%s", snprintf(buf, sizeof(buf), LD_PRELOAD_ENV "=%s/%s%s%s",