《程序员的自我修养》 p92
参考资料:
http://blog.csdn.net/fandelion/article/details/6258319
http://en.wikipedia.org/wiki/Weak_symbol
实际应用: glibc/include/libc-symbols.h
DevOps
《程序员的自我修养》 p92
参考资料:
http://blog.csdn.net/fandelion/article/details/6258319
http://en.wikipedia.org/wiki/Weak_symbol
实际应用: glibc/include/libc-symbols.h
转自: http://my.oschina.net/alphajay/blog/49941
下面我向大家介绍一下使用gdb修改可执行文件中的代码和变量的方法。
另,在GDB文档中介绍这个方法也 能修改CORE文件的内容,本人未验证。
在 一般情况下GDB是以只读方式打开可执行文件的,如果需要改变可执行文件,需要在读入文件以前,用GDB启动参数“–write”或者命令“set write on”用可读写方式打开可执行文件。如果文件已经打开了可执行文件,就需要使用exec-file重新以读写方式打开可执行文件,注意如果你还没打开可执行文件,就一定要使用file命令读入,因为exec-file不会重新读入符号信息。
还有要注意的是,因为修改只能修改section的内容,所以能修改的变量只能是非0的全局变量,内容是O的变量会被放入bss。
1.c:
1 2 3 4 5 6 7 8 |
#include <stdio.h> int a = 1; int main(int argc,char *argv[],char *envp[]) { printf ("%d\n", a); return 0; } |
gcc -g 1.c
./a.out
1
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#gdb GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". (gdb) set write on #打开功能 (gdb) file ./a.out #打开文件 Reading symbols from /home/teawater/gdb/a.out...done. (gdb) p a = 100 #修改变量的文件中的值 $1 = 100 |
./a.out
100
下面举例修改代码内容:
1.c:
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <stdio.h> void cool (void) { printf ("Call function cool.\n"); } int main(int argc,char *argv[],char *envp[]) { cool (); return 0; } |
#gcc -g 1.c
#./a.out
1 |
Call function cool. |
修改代码内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
gdb --write ./a.out #使用--write直接打开可写功能 GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu"... (gdb) disas cool Dump of assembler code for function cool: 0x000000000040050c <cool+0>: push %rbp #注意改之前这条指令 0x000000000040050d <cool+1>: mov %rsp,%rbp 0x0000000000400510 <cool+4>: mov $0x40062c,%edi 0x0000000000400515 <cool+9>: callq 0x4003f8 <puts@plt> 0x000000000040051a <cool+14>: leaveq 0x000000000040051b <cool+15>: retq End of assembler dump. (gdb) set *(unsigned char *)(0x000000000040050c) = 0xc3 #修改指令 (gdb) disas cool Dump of assembler code for function cool: 0x000000000040050c <cool+0>: retq #改之后这指令发生了变化 0x000000000040050d <cool+1>: mov %rsp,%rbp 0x0000000000400510 <cool+4>: mov $0x40062c,%edi 0x0000000000400515 <cool+9>: callq 0x4003f8 <puts@plt> 0x000000000040051a <cool+14>: leaveq 0x000000000040051b <cool+15>: retq End of assembler dump. |
. /a.out #现在没有输出了 因为cool函数直接返回了
Proxifier是一款功能非常强大的socks5客户端,可以让不支持通过代理服务器工作的网络程序能通过HTTPS或SOCKS代理或代理链。支持 64位系统,支持Xp,Vista,Win7,MAC OS ,支持socks4,socks5,http代理协议,支持TCP,UDP协议,可以指定端口,指定IP,指定程序等运行模式,兼容性非常好。有点类似SOCKSCAP。
下载地址: http://www.proxifier.com/
注册码:
MBZKT-ZWTSL-M8X24-3AN7T-NRWU6
JBZEM-M2HY9-C3SW3-6SKQC-MVNXN
Q7ZB5-A35HX-8GWYW-T47T4-9FNVX
55ZE3-SWXN2-CMM2N-22MQQ-NLB95
JCZBX-A3N3F-9DWY5-327V5-DKUXX
LPZLA-FW4R4-NV52E-Q9RYW-PH3ZY
也可以用 注册机: Proxifier.v3.0.Standard.Edition key
相关资料:
百度百科: http://baike.baidu.com/view/3430720.htm
相关资料: http://www.duba.net/c/2004/11/29/154980.shtml
关于http代理、https代理、socks4、socks5代理的不同:
1 2 3 4 5 6 7 8 9 10 11 |
HTTP代理: 能够代理客户机的HTTP访问,主要是代理浏览器访问网页,它的端口一般为80、8080、3128等; HTTPS代理: 如果你访问通过HTTP服务访问一些敏感的信息,可能会被GFW给处理,禁止访问,这是可以通过HTTPS代理服务器来访问,如: 浏览器 <------ 80端口,明文 -----> 本地代理客户端 <------ https加密 ----> https代理服务器 <--- 明文 ---> 目标服务器 注意另外一个概念: 你访问的是一个https的站点,但是该站点ip被处理了,这时候使用这种形式的https代理服务器就不好使了,会出现证书错误的问题,就需要用到下面的socks代理了 SOCKS代理: SOCKS代理与其他类型的代理不同,它只是简单地传递数据包,而并不关心是何种应用协议,既可以是HTTP请求,所以SOCKS代理服务器比其他类型的代理服务器速度要快得多。 SOCKS代理又分为SOCKS4和SOCKS5,二者不同的是SOCKS4代理只支持TCP协议(即传输控制协议),而SOCKS5代理则既支持TCP协议又支持UDP协议(即用户数据包协议),还支持各种身份验证机制、服务器端域名解析等。SOCK4能做到的SOCKS5都可得到,但SOCKS5能够做到的SOCK4则不一定能做到,比如我们常用的聊天工具QQ在使用代理时就要求用SOCKS5代理,因为它需要使用UDP协议来传输数据 |
转载:http://www.linuxso.com/linuxxitongguanli/624.html
http://www.linuxso.com/uploads/soft/101018/ss5-3.6.1-1.tar.gz 安装步骤如下
推荐官网最新版 3.8.4-1 http://nchc.dl.sourceforge.net/project/ss5/ss5/3.8.4-1/ss5-3.8.4-1.tar.gz
socks5代理的功能和作用这里我就不罗嗦了---------------
yum -y install gcc automake make
2.安装socks5必要的包
yum -y install pam-devel openldap-devel cyrus-sasl-devel
3.下载,编译安装ss5(socks5)
wget http://www.linuxso.com/uploads/soft/101018/ss5-3.6.1-1.tar.gz
tar zxvf ss5-3.6.1-1.tar.gz
cd ss5-3.6.1
./configure
make
make install
#启动ss5服务
/etc/init.d/ss5 start
如果没办法启动,则是权限问题
# SHost SPort Authentication
#
auth 0.0.0.0/0 – –
为
# SHost SPort Authentication
#
auth 0.0.0.0/0 – u
在 /etc/opt/ss5/ss5.passwd 中添加 用户名和密码 如:
test test
使用用户验证,重启ss5服务
/etc/init.d/ss5 restart
如果有错误可以跟踪日志:
配置有密码的SOCKS5代理之后,迅雷可以配置代理下载,但是我测试遨游打不开网页。
除非配置不使用用户和密码,遨游才可以代理上网,可能是流量器内置的SOCKS5客户端有问题。
至于端口号怎么修改,我还没有找到,在源文件里面修改config.h 但是编译之后端口还是1080.
以后发现了再修改,我使用SS5只是用来突破学校的BT下载限制,再测试之后会告诉大家如何修改端口号。
先前我也百度谷歌了半天,不过发现他们用的都是老版的SS5,我已经看了很多,大家没必要了,有价值的内容,我都贴到这里面了。
欢迎测试过的朋友在下面留言,也可以加我们Linux安全网的QQ群交流 群号:11153255
相关资料: http://linux.net527.cn/fuwuqiyingyong/Squidfuwuqi/2802.html
1. 冒号十六进制记法
冒号十六进制记法为每个16位的值用十六进制值表示,各值之间用冒号分隔,如:
68E6:8C64:FFFF:FFFF:0:1180:960A:FFFF
2. 零压缩,即一连串的零可以为一对冒号所取代。
FF05:0:0:0:0:0:B3,可以写成FF05::B3
在一个地址中只能使用一次零压缩
3. 点分十进制法的后缀
0:0:0:0:0:0:128.10.2.1,再使用零压缩即可得出为::128.10.2.1
4. CIDR的斜线表示法仍然可用,60位的前缀12AB00000000CD3可记为:
12AB:0000:0000:CD30:0000:0000:0000:0000/60
或
12AB::CD30:0:0:0:0/60或12AB:0:0:CD30::/60
1. gai 是什么?
gai就是 GetAddrInfo() 的意思
相关资料:
http://qdugnx.7ta.cn/Article/2012520/963721/
gethostbyname和getaddrinfo都是做地址解析的,但是二者表现却有所差异,一定程度上来讲,getaddrinfo是意欲取代gethostbyname的,似乎这些和IPv6没有太大关系,但是gethostbyname中没有关于IPv6的逻辑,而getaddrinfo中是有关于IPv6的逻辑的;在php中实现php_network_getaddresses 时,判断了是否支持 getaddrinfo,如果支持则使用getaddrinfo,否则使用gethostbyname。
如果使用了getaddrinfo,当一个域名可以解析出过个ip地址时,则会根据rfc3484的说明来返回一个地址。而且如果使用strace跟踪的话,会发现多个ip地址都会使用数据包的socket类型connect一下(见西面说明)。
遇到的问题是:
1. getaddrinfo的实现可能会出现死锁的情况。
2. 如果一个域名可以返回多个IP,在php中,使用gethostbyname则根据dns返回的顺序,返回第一个ip(gethostbynamel()函数会返回所有的ip),参看php_gethostbyname(…)函数; 而在file_get_contents、fsockopen等函数中的域名解析则可能(编译时会自动检查是否支持,参看configure.in,搜索getaddrinfo,相关预定义常量HAVE_GETADDRINFO)会总使用同一个ip,其ip选择策略参看 rfc3484. 具体的算法实现参考glibc/sysdeps/posix/getaddrinfo.c 中的getaddrinfo()函数和rfc3484_sort(…)函数;这个就给负载均衡带来了麻烦
3. 对于域名返回多个IP地址时,使用getaddrinfo()函数会出现多次的数据包类型的connect()操作,如下:
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“172.16.139.229”)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(54610), sin_addr=inet_addr(“10.49.4.65”)}, [16]) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“10.49.4.245”)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(54610), sin_addr=inet_addr(“10.49.4.65”)}, [16]) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“10.77.7.251”)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(54610), sin_addr=inet_addr(“10.49.4.65”)}, [16]) = 0
为什么要connect呢?
这个也是因为域名返回了多个IP地址,为了决定返回哪一个IP地址,要根据rfc3484的算法来返回;而rfc3484算法是在计算源ip和目标ip之间的距离的,对于多接口的主机来讲,目的ip不同则源ip也可能不同(上面例子中的源ip是相同的),所以就借用了connect来获取一下如果要去往某个目的ip,使用的源ip会是什么,这里使用了数据包类型的socket做连接,这样不会产生一次真正的连接,也就是说,connect是为getsockname做准备的。
4. 不知道PHP在什么时候已经默认支持IPv6了(至少php5.3.3已经这样了),当然必须支持getaddrinfo才能启用IPv6的一些逻辑,如果编译时支持了IPv6,但是运行环境中没有启用IPv6,会在访问http资源的时候,使用strace会发现如下一次系统调用:
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = -1 EAFNOSUPPORT (Address family not supported by protocol)
这个是在检查是否支持IPv6.
相关代码参看:main/network.c中的函数 php_network_getaddresses(…)
5. 关于gethostbyname的glibc实现参看: glibc/resolv/gethnamaddr.c
或许你无法通过ctag的方式跳转到 gethostbyname定义的地方,是因为该函数定义的前面有一个奇怪的宏: libresolv_hidden_proto (gethostbyname2) , 因为后面没有分号,所以, gethostbyname就被隐藏了:
6. 关于使用getaddrinfo不能做到dns轮询的解决办法
使用gethostbyname来解析出ip,如:
1 2 3 4 5 6 7 8 9 10 11 |
<?php function http($url) { $curl = curl_init(); $arr = parse_url($url); $host = $arr["host"]; $ip = gethostbyname($host); $url = preg_replace("#^http([s]?)://$host#", "http\$1://$ip", $url); curl_setopt($curl, CURLOPT_HTTPHEADER, "Host: $host"); ... } |
(gdb) bt
#0 0x00000031a58d4590 in getsockname () from /lib64/libc.so.6
#1 0x00000031a58f4eb1 in __check_pf () from /lib64/libc.so.6 // __check_pf 是check protol family的意思
#2 0x00000031a58bd744 in getaddrinfo () from /lib64/libc.so.6
#3 0x00000031a642eb70 in Curl_getaddrinfo () from /usr/lib64/libcurl.so.3
#4 0x00000031a640be2d in Curl_resolv () from /usr/lib64/libcurl.so.3
#5 0x00000031a641a7ce in Curl_connect () from /usr/lib64/libcurl.so.3
#6 0x00000031a6425fd1 in ?? () from /usr/lib64/libcurl.so.3
#7 0x00000031a642814a in Curl_perform () from /usr/lib64/libcurl.so.3
#8 0x0000000000406adc in ?? ()
#9 0x00000031a581d994 in __libc_start_main () from /lib64/libc.so.6
#10 0x0000000000401de9 in ?? ()
#11 0x00007fffea5fec38 in ?? ()
#12 0x0000000000000000 in ?? ()
测试脚本:
file_get_contents(“http://phpor.net/xxx.php”);
strace过程:
[root@ja-4-65 ~]# strace -e network php b.php
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = -1 EAFNOSUPPORT (Address family not supported by protocol) 虽然编译时声明支持IPv6,但是还是再检查是否支持IPv6, 见代码段1
socket(PF_FILE, SOCK_STREAM, 0) = 3
connect(3, {sa_family=AF_FILE, path=”/var/run/nscd/socket”}, 110) = -1 ENOENT (No such file or directory)
socket(PF_FILE, SOCK_STREAM, 0) = 3
connect(3, {sa_family=AF_FILE, path=”/var/run/nscd/socket”}, 110) = -1 ENOENT (No such file or directory)
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr(“172.16.108.100”)}, 28) = 0
send(3, “\342=\1\0\0\1\0\0\0\0\0\0\6ilogin\4sina\3com\2cn\0″…, 36, MSG_NOSIGNAL) = 36
recvfrom(3, “\342=\201\200\0\1\0\3\0\4\0\4\6ilogin\4sina\3com\2cn\0″…, 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr(“172.16.108.100”)}, [16]) = 220
socket(PF_NETLINK, SOCK_RAW, 0) = 3
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, pid=17124, groups=00000000}, [12]) = 0
sendto(3, “\24\0\0\0\26\0\1\3\246m\201P\0\0\0\0\0\0\0\0”, 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{“<\0\0\0\24\0\2\0\246m\201P\344B\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1″…, 4096}], msg_controllen=0, msg_flags=0}, 0) = 196
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{“\24\0\0\0\3\0\2\0\246m\201P\344B\0\0\0\0\0\0\1\0\0\0\10\0\1\0\177\0\0\1″…, 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“10.77.7.251”)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(37927), sin_addr=inet_addr(“10.49.4.65”)}, [16]) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“172.16.139.229”)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(37927), sin_addr=inet_addr(“10.49.4.65”)}, [16]) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“10.49.4.245”)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(37927), sin_addr=inet_addr(“10.49.4.65”)}, [16]) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr(“10.49.4.245”)}, 16) = -1 EINPROGRESS (Operation now in progress)
getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
send(3, “GET /xxxx.php HTTP/1.0\r\n”, 30, MSG_DONTWAIT) = 30
send(3, “Host: phpor.net\r\n”, 26, MSG_DONTWAIT) = 26
send(3, “\r\n”, 2, MSG_DONTWAIT) = 2
recv(3, “HTTP/1.1 200 OK\r\nDate: Fri, 19 O”…, 8192, MSG_DONTWAIT) = 284
recv(3, “”, 8192, MSG_DONTWAIT) = 0
recv(3, “”, 8192, MSG_DONTWAIT) = 0
相关代码:
代码段1:php-5.3.3/main/network.c
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# if HAVE_IPV6 /* probe for a working IPv6 stack; even if detected as having v6 at compile * time, at runtime some stacks are slow to resolve or have other issues * if they are not correctly configured. * static variable use is safe here since simple store or fetch operations * are atomic and because the actual probe process is not in danger of * collisions or race conditions. */ if (ipv6_borked == -1) { int s; s = socket(PF_INET6, SOCK_DGRAM, 0); if (s == SOCK_ERR) { ipv6_borked = 1; } else { ipv6_borked = 0; closesocket(s); } } hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC; # endif |
man页: http://www.kernel.org/doc/man-pages/online/pages/man5/nsswitch.conf.5.html
中文说明:
nsswitch.conf:服务搜索顺序
action
action的取值如下:
l return——返回到调用例程,带有返回值,或者不带返回值。
l continue——继续执行下一个方法。任何返回值都会被下一个方法找到的值覆盖。
示例
举例来说,下面这行取自nsswitch.conf文件,它的作用是让系统首先使用DNS来搜索给定主机的IP地址。DNS方法后面的动作项是测试该方法所返回的状态是否为“非(!)UNAVAIL”。
如果DNS方法没有返回UNAVAIL(!UNAVAIL),也就是说DNS返回SUCCESS、NOTFOUND或者TRYAGAIN,那么系统就会执行与该STATUS相关的动作(return)。其结果就是,只有在DNS服务器不可用的情况下才会使用后面的方法(files)。如果DNS服务器并不是不可用(两次否定之后就是“可用”),那么搜索返回域名或者报告未找到域名。只有当服务器不可用的时候,搜索才会使用files方法(检查本地的/etc/hosts文件)。