Daily Tips - Vol2
用patchelf设置binary路径
使用 --set-interpreter可以设置解释器路径,--set-rpath设置搜索动态库的路径。其中$ORIGIN是一个特殊的值,意为“根据当前的目录,相对地寻找lib”. 但是注意,这个选项对于–interpreter无效。
一个错误示范:
1
2
3
4
5
6
7
8
9
10
11
12
(venv14) woc@myarch:ehaxCTF/revenge_womp $ ls .
handout handout_revenge_of_womp_womp.zip pwn
(venv14) woc@myarch:ehaxCTF/revenge_womp $ ls handout
ld.so libc.so.6
(venv14) woc@myarch:ehaxCTF/revenge_womp $ sudo patchelf --set-rpath '$ORIGIN/handout' ./pwn
(venv14) woc@myarch:ehaxCTF/revenge_womp $ sudo patchelf --set-interpreter '$ORIGIN/handout/ld.so' ./pwn
(venv14) woc@myarch:ehaxCTF/revenge_womp $ ldd ./pwn
linux-vdso.so.1 (0x00007f8599851000)
libc.so.6 => /ctf/ehaxCTF/revenge_womp/handout/libc.so.6 (0x00007f8599600000)
$ORIGIN/handout/ld.so => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f8599853000)
(venv14) woc@myarch:ehaxCTF/revenge_womp $ ./pwn
zsh: no such file or directory: ./pwn
上面错误地对interpreter设置了无效的$ORIGIN,导致其fallback到了系统路径。
正确做法:
1
sudo patchelf --set-interpreter "$(pwd)/handout/ld.so" pwn
查看libc字符串
1
strings -a ./libc.so.6 | rg 'GNU C Library|release version|glibc'
在docker内部也走dae代理
修改/etc/dae/config.dae, 找到这一行:
1
# lan_interface: docker0
删除注释
docker和宿主机共享目录
[TODO]
另外,可以通过将docker内部文件所有者uid/gid和宿主机的改成一致(usermod, groupmod命令可以做到)
注意:如果宿主机上删除了原本的目录,重新建立了一个同名的,大概率也会造成docker无法启动:
1
OCI runtime exec failed: exec failed: unable to start container process: current working directory is outside of container mount namespace root -- possible container breakout detected
可能是因为docker检查inode和原来的不同?
设定不需要root权限即可执行某个代码
visudo可以修改user/group执行特定命令的权限。比如要abc用户不需要sudo密码即可执行docker:
1
2
woc ALL=(ALL) NOPASSWD: /usr/bin/docker.
还可以匹配更多的参数:
1
woc ALL=(ALL) NOPASSWD: /usr/bin/systemctl start dae.service, /usr/bin/systemctl stop dae.service, /usr/bin/systemctl restart dae.service
然后:
def main [command : string] {
match $command {
start => {
^sudo systemctl start dae.service
echo $"(ansi green)Start(ansi reset) proxy"
}
stop => {
^sudo systemctl stop dae.service
echo $"(ansi red)Stop(ansi reset) proxy"
}
restart => {
^sudo systemctl restart dae.service
echo $"(ansi green)Restart(ansi reset) proxy"
}
_ => {
echo $"(ansi red)Invalid parameter:($command) (ansi reset) proxy"
exit -1
}
}
}
实现“exclude”
grep -v 可以实现“反向”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(venv14) woc@myarch:~/NativeDigger ‹main*›$ la
. AGENT.md config.toml faq .gitignore old README.md re_bk.py resume.txt tool_info.txt
.. config diagnostic .git load_env.py __pycache__ re_ai.py report src
(venv14) woc@myarch:~/NativeDigger ‹main*›$ la | grep -v "git"
.
..
AGENT.md
config
config.toml
diagnostic
faq
load_env.py
old
__pycache__
README.md
re_ai.py
re_bk.py
report
resume.txt
src
tool_info.txt
接下来删除.和.. , grep -E可以增加”或”的功能,对比效果:
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
28
(venv14) woc@myarch:~/NativeDigger ‹main*›$ la | grep -v "\.git|\.|\.\."
.
..
AGENT.md
config
config.toml
diagnostic
faq
.git
.gitignore
load_env.py
old
__pycache__
README.md
re_ai.py
re_bk.py
report
resume.txt
src
tool_info.txt
(venv14) woc@myarch:~/NativeDigger ‹main*›$ la | grep -vE "\.git|\.|\.\."
config
diagnostic
faq
old
__pycache__
report
src
但是这样发现AGENT.md等名字中含有.的都会被过滤掉,所以需要更加精准的匹配:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(venv14) woc@myarch:~/NativeDigger ‹main*›$ la | grep -Ev '^(\.|\.\.|\.git)$'
AGENT.md
config
config.toml
diagnostic
faq
.gitignore
load_env.py
old
__pycache__
README.md
re_ai.py
re_bk.py
report
resume.txt
src
tool_info.txt
接着通过xargs传递到后面的命令. xargs通过管道接受输入,将其格式化后喂给后面的命令。而且有一个非常有用的功能: 先通过 -I 参数指定一个占位符,然后在后面写上命令,就能实现类似于sprintf的效果:
1
2
# 把除了.git外的所有东西复制到另一仓库
(venv14) woc@myarch:~/NativeDigger ‹main*›$ la | grep -Ev '^(\.|\.\.|\.git)$' | xargs -I {} cp -r {} ~/repo/ReAI
补充:xargs 指定的占位符默认情况下只能替换一次,如果想要多次,就要用sh -c来执行包装后的整体:
1
2
3
4
5
6
7
8
9
10
11
12
13
(venv14) woc@myarch:dotfiles/hypr ‹main*›$ ls . | grep conf | xargs -I {} echo {}; cat {}
cursor.conf
hyprland.conf
process.conf
window.conf
workplace.conf
cat: {}: No such file or directory
(venv14) woc@myarch:dotfiles/hypr ‹main*›$ ls . | grep conf | xargs -I {} "echo {}; cat {}"
xargs: echo {}; cat {}: No such file or directory
# 正确写法
(venv14) woc@myarch:dotfiles/hypr ‹main*›$ ls . | grep conf | xargs -I {} sh -c "echo {}; cat {}"
......
在脚本中编写配置文件
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env bash
HOST="127.0.0.1"
PORT="8080"
DEBUG="true"
cat > app.conf <<EOF
host=$HOST
port=$PORT
debug=$DEBUG
EOF
其中<<是here document写法,指定一个终止符号(名字可以自选,不必用EOF). 注意:指定的终止符加引号时,会禁止展开其中的shell变量:
1
2
3
4
5
6
7
8
9
10
(venv14) woc@myarch:~/tmpBox $ cat > test.conf <<EOF
heredoc> $PATH
heredoc> EOF
(venv14) woc@myarch:~/tmpBox $ cat test.conf
/home/woc/.bun/bin:/home/woc/.cabal/bin:/home/woc/.ghcup/bin:/home/woc/venv14/bin:/home/woc/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
(venv14) woc@myarch:~/tmpBox $ cat > test.conf <<'EOF'
heredoc> $PATH
heredoc> EOF
(venv14) woc@myarch:~/tmpBox $ cat test.conf
$PATH
解决ida pro在niri下崩溃的问题
ida-pro-9.2 linux版在kde plasma下运行正常,hyprland下也能使用,但是到了niri会出现问题: (前提:关闭虚拟环境,目前没有找到让idapyswitch用虚拟环境的方法,如果在运行venv的命令行launch ida,可能会因为python版本不匹配而报错:ModuleNotFoundError: No module named ‘_struct’)
关闭了虚拟环境后:
1
2
3
woc@myarch:~ $ /opt/ida9/ida
malloc(): unaligned tcache chunk detected
[1] 29035 IOT instruction (core dumped) /opt/ida9/ida
把strace日志丢给ai,然后给出建议:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- IDA 9 自带的 Qt6 Wayland decoration 插件
- 在 Niri 这个 Wayland 环境下触发了堆损坏/非法释放
- KDE 和 Hyprland 不触发,说明是 compositor/Wayland 路径差异触发,不是 IDA 安装整体损坏
最实用的规避方式有两个:
1. 强制走 XWayland:
QT_QPA_PLATFORM=xcb /opt/ida9/ida
2. 继续走 Wayland,但尽量绕开窗口装饰路径:
QT_WAYLAND_DISABLE_WINDOWDECORATION=1 /opt/ida9/ida
如果还不行,再试:
QT_QPA_PLATFORM=wayland QT_WAYLAND_DISABLE_WINDOWDECORATION=1 /opt/ida9/ida
这下确实不会崩溃了,但是在写入.desktop文件的时候,发现再用rofi启动还是没反应:
1
2
3
4
5
6
7
8
9
[Desktop Entry]
Type=Application
Version=1.5
Name=IDA Professional 9.2
Comment=Interactive Disassembler Professional 9.2
Icon=/opt/ida9/appico.png
Exec=QT_QPA_PLATFORM=xcb /opt/ida9/ida
Terminal=false
Categories=Development
原来这里的Exec并不是严格地把后面的东西丢给shell, 启动器会把 QT_QPA_PLATFORM=xcb 当成“可执行文件名”,结果自然没反应. 解决方法:使用/usr/bin/env触发
1
2
3
4
5
6
7
8
9
[Desktop Entry]
Type=Application
Version=1.5
Name=IDA Professional 9.2
Comment=Interactive Disassembler Professional 9.2
Icon=/opt/ida9/appico.png
Exec=/usr/bin/env QT_QPA_PLATFORM=xcb /opt/ida9/ida
Terminal=false
Categories=Development
yay遇到could not open file /var/lib/pacman/sync/core.db: Unrecognized archive format的解决方法
https://bbs.archlinux.org/viewtopic.php?id=135310
1
2
sudo rm -R /var/lib/pacman/sync/
sudo pacman -Syu
找到ppid
https://askubuntu.com/questions/153976/how-do-i-get-the-parent-process-id-of-a-given-child-process
ps -o ppid= 2072 可以找到pid=2072的ppid
pacman/yay查找已经安装的软件
当想要更新一个软件的时候,如果忘记了具体名字,可以用pacman -Q查找当前已经安装的所有包,然后过滤.
nushell脚本技巧
- 内部与外部命令 nushell内建了一些命令,当在脚本中写
ls时,默认会使用nushell内部的ls. 但是很多情况下,我们想要使用系统里的命令,解决方法:在命令前加上^:^sudo start_proxy - optional参数 加上
?def main [command?: string] - 将命令结果/变量嵌入到字符串 使用
(),内部放$var或者command. 同时字符串外面也要写$:"help" => { echo $"options:\n ($options)" },注意在前面加了
$的字符串中,内部的()会默认内部是一个命令,比如:1
let target = (input $"Choose a venv (0-($venv_entries|length)):")
结果或报错,因为
0-3并不是一个命令,但是外层的括号尝试对其进行求值。可以通过对括号进行转义来解决:1
let target = (input $"Choose a venv \(0-($venv_entries|length)\):")
- “block”的返回值 如果写了:
"help" => { echo "options:\n" echo $options },会发现,只输出了后面的值。这是因为echo本身只是返回一个值,并不打印,真正打印的是print. 这个block终止后,会调用最后的返回值来显示,因此后面的echo返回值会覆盖前面的. 解决方法:如果想要输出,用print而不是echo
"help" => { print "options:" print $options }, - 检验环境变量是否为空 如果直接使用
$env.VIRTUAL_ENV这种形式,在该变量不存在的时候,会直接报错退出。 方法:使用“可选访问”:1
let current = $env.VIRTUAL_ENV?
- 对管道中的数据进行算数运算 可以使用
$in:1
let target = (input $"Choose a venv \(0-($venv_entries | length | $in - 1)\):")
不过需要注意:
$in和后面的符号之间要有空格,否则会报错. (变量名和符号不能连接是nushell的特性,比如$abc< 1也会报错) - 加载某个bash脚本 nushell和bash/zsh语法不兼容,但是
1 2
deactive source xxx/bin/activate
都是给标准shell准备的. 如果想要在nushell中执行,需要找到配套的
avtivate.nu而且nushell现在更加鼓励使用overlay的写法:1 2
overlay use $"($target_venv_path)/bin/activate.nu" overlay hide
但是在我的系统上,是用zsh来启动nu,执行脚本。子进程无法直接改变父进程的环境,因此尝试将结果返回一个命令,让zsh再执行. (不过这种做法并不优雅)
- if-else 错误写法(会把else当成命令,然后提示“not found”):
1 2 3 4
if xxx { } else { }正确写法:把
}和else写在一行(这也太古怪了):1 2 3
if xxx { } else { } - 访问列表 静态列表可以直接通过
.访问:1
$list.2
如果想要动态