Post

Daily Tips - Vol2

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
    

    如果想要动态

This post is licensed under CC BY 4.0 by the author.