ขอบคุณSasha Pachevสำหรับการแฮ็คที่ดีข้างต้น
vpnagentd
/etc/resolv.conf
ยังยุ่งกับการจำแนกโดยการเขียนทับการเปลี่ยนแปลงที่เกิดขึ้นกับ ฉันแก้ไขมันด้วยการชนะการแข่งกับมันในที่สุด:
#!/bin/bash
dnsfix() {
[ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup #>/dev/null
do
cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
done
chattr +i /etc/resolv.conf
diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null
}
while ! dnsfix
do
echo "Retrying..."
chattr -i /etc/resolv.conf
done
อย่าลืมchattr -i /etc/resolv.conf
เมื่อตัดการเชื่อมต่อ
ฉันพยายามที่จะแก้ปัญหาโดยขัดขวางการโทรกลับเช่นวิธีการด้านบน แต่ยังไม่พบวิธีการติดต่อกลับหรือวิธีการที่สอดคล้องกัน
Update1 / 2: การstrace
เปิดเผยที่vpnagentd
ใช้inotify
API เพื่อตรวจสอบการเปลี่ยนแปลงไฟล์ตัวแก้ไข จากนั้นเป็นต้นไปมันตกต่ำ นี่คือแฮ็คเพิ่มเติม:
int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
return 0;
}
นั่นเป็นเรื่องที่เกินความจริงเล็กน้อยเนื่องจากได้ปิดใช้งานการดูไฟล์ทั้งหมดสำหรับเอเจนต์ แต่ดูเหมือนว่าจะใช้ได้
สคริปต์ตัวห่อลูกค้า vpn ด้านล่างรวมการทำงานทั้งหมด (อัปเดตเพื่อรวมแฮ็คเพิ่มเติมนี้) chattr
ไม่ได้ใช้ / จำเป็นอีกต่อไป
อัปเดต 3: แก้ไขการตั้งค่าชื่อผู้ใช้ / รหัสผ่านในสคริปต์ ตอนนี้ใช้vpn.conf
ไฟล์ที่มีรูปแบบที่อธิบายด้านล่าง (และสิทธิ์แบบรูทเท่านั้น)
#!/bin/bash
# Change this as needed
CONF="/etc/vpnc/vpn.conf"
# vpn.conf format
#gateway <IP>
#username <username>
#password <password>
#delete_routes <"route spec"...> eg. "default gw 0.0.0.0 dev cscotun0"
#add_routes <"route spec"...> eg. "-net 192.168.10.0 netmask 255.255.255.0 dev cscotun0" "-host 10.10.10.1 dev cscotun0"
ANYCONNECT="/opt/cisco/anyconnect"
usage() {
echo "Usage: $0 {connect|disconnect|state|stats|hack}"
exit 1
}
CMD="$1"
[ -z "$CMD" ] && usage
ID=`id -u`
VPNC="$ANYCONNECT/bin/vpn"
dnsfix() {
[ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null
do
cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
done
# chattr +i /etc/resolv.conf
diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null
}
case "$CMD" in
"connect")
[ $ID -ne 0 ] && echo "Needs root." && exit 1
HOST=`grep ^gateway $CONF | awk '{print $2}'`
USER=`grep ^user $CONF | awk '{print $2}'`
PASS=`grep ^password $CONF | awk '{print $2}'`
OLDIFS=$IFS
IFS='"'
DEL_ROUTES=(`sed -n '/^delete_routes/{s/delete_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF`)
ADD_ROUTES=(`sed -n '/^add_routes/{s/add_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF`)
IFS=$OLDIFS
/usr/bin/expect <<EOF
set vpn_client "$VPNC";
set ip "$HOST";
set user "$USER";
set pass "$PASS";
set timeout 5
spawn \$vpn_client connect \$ip
match_max 100000
expect {
timeout {
puts "timeout error\n"
spawn killall \$vpn_client
exit 1
}
">> The VPN client is not connected." { exit 0};
">> state: Disconnecting" { exit 0};
"Connect Anyway?"
}
sleep .1
send -- "y\r"
expect {
timeout {
puts "timeout error\n"
spawn killall \$vpn_client
exit 1
}
"Username:"
}
sleep .1
send -- "\$user\r"
expect {
timeout {
puts "timeout error\n"
spawn killall \$vpn_client
exit 1
}
"Password: "
}
send -- "\$pass\r";
expect eof
EOF
sleep 2
# iptables
iptables-save | grep -v DROP | iptables-restore
# routes
for ROUTE in "${DEL_ROUTES[@]}"
do
# echo route del $ROUTE
route del $ROUTE
done
for ROUTE in "${ADD_ROUTES[@]}"
do
# echo route add $ROUTE
route add $ROUTE
done
# dns
while ! dnsfix
do
echo "Try again..."
# chattr -i /etc/resolv.conf
done
echo "done."
;;
"disconnect")
# [ $ID -ne 0 ] && echo "Needs root." && exit 1
# dns
# chattr -i /etc/resolv.conf
$VPNC disconnect
;;
"state"|"stats")
$VPNC $CMD
;;
"hack")
[ $ID -ne 0 ] && echo "Needs root." && exit 1
/etc/init.d/vpnagentd stop
sleep 1
killall -9 vpnagentd 2>/dev/null
cat - >/tmp/hack.c <<EOF
#include <sys/socket.h>
#include <linux/netlink.h>
int _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv()
{
int fd=50; // max fd to try
char buf[8192];
struct sockaddr_nl sa;
socklen_t len = sizeof(sa);
while (fd) {
if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
if (sa.nl_family == AF_NETLINK) {
ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
}
}
fd--;
}
return 0;
}
int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
return 0;
}
EOF
gcc -o /tmp/libhack.so -shared -fPIC /tmp/hack.c
mv /tmp/libhack.so $ANYCONNECT
sed -i "s+^\([ \t]*\)$ANYCONNECT/bin/vpnagentd+\1LD_PRELOAD=$ANYCONNECT/lib/libhack.so $ANYCONNECT/bin/vpnagentd+" /etc/init.d/vpnagentd
rm -f /tmp/hack.c
/etc/init.d/vpnagentd start
echo "done."
;;
*)
usage
;;
esac