Debian forky上安装RabbitMQ

erlang版本是 27.3
apt install rabbitmq-server

在大多数系统上,节点应该能够以所有默认设置启动和运行。默认会创建一个用户 guest,密码为 guest

为 RabbitMQ 创建一个管理员用户。您可以使用以下命令创建它:
rabbitmqctl add_user admin password

为您的管理员帐户设置标签:
rabbitmqctl set_user_tags admin administrator

设置适当的权限:
rabbitmqctl set_permissions -p / admin “.*” “.*” “.*”

ejabberd安装配置

1. 安装
apt install ejabberd

2. 配置

修改 ejabberd.xml
1) 域名
hosts:
# – localhost
– softs.im
2) 证书
certfiles:
# – “/etc/ejabberd/ejabberd.pem”
– /etc/ejabberd/softs.im/fullchain.pem
– /etc/ejabberd/softs.im/privkey.pem

3) 并确保 access_rules 下的 configure 权限允许该管理员:

access_rules:
configure:
allow: admin

4) 添加管理员

acl:
admin:
user:
– “cmcc@softs.im”

5) 如果需要让 Gajim支持文件传输,需要打开mod_http_upload
第一处,将 /upload: mod_http_upload 这一行的 #号 注释去掉
port: 5443
ip: “::”
module: ejabberd_http
tls: true
protocol_options: ‘TLS_OPTIONS’
request_handlers:
/api: mod_http_api
/bosh: mod_bosh
## /captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
在 modules: 下面开启 mod_http_upload, 也是将相关的 #号 注释去掉

mod_http_upload:
put_url: https://@HOST@:5443/upload
docroot: “/var/upload”
注意,我添加了一个 docroot, 服务器会将接收到的文件存在这个目录

3.
重启 ejabberd
ejabberdctl restart

4.
注册管理员
ejabberdctl register admin localhost password
(将 admin、localhost 和 password 替换为您的自定义用户名、域名和密码)

5.
访问 https://softsim:5280/admin/ 来管理

特别强调:
XMPP 的 文件传输体验 不只是客户端问题,最好是服务器上也给予支持。

P2P直传(老方式),在 conversation和dino上支持,但NAT环境容易失败,并且传输慢
HTTP Upload(推荐) 文件先上传服务器

rust中的引用为什么可以直接比较大小

Rust 中两个引用(如 &T)可以直接比较大小,是因为 Rust 的标准库为实现了 Ord 或 PartialOrd trait 的类型 T 的引用类型 &T 自动实现了这些 trait。具体来说,当比较 &a 和 &b 时,实际上是在比较它们所指向的底层数据 a 和 b 的值

原因有以下两点:
1. 智能隐式解引用(Dereferencing): Rust 的比较运算符(<, >, <=, >=)会处理引用。编译器在比较时,会自动深入引用层级,比较指向的实际数值,而非引用本身的内存地址。

2. Trait 自动实现: Rust 标准库中存在类似 impl Ord for &T 的定义。即如果类型 T 本身是可以比较顺序的(实现了 Ord),那么 &T 也自动拥有比较顺序的能力。

或者这么来理解: 在 Rust 中,比较运算符(如 >, <, ==)实际上是对标准库中 Trait(特征)的语法糖。比如 > 对应的是 PartialOrd 这个特征(Trait), 如果一个类型 T 可以比较大小,那么它的引用 &T 也可以比较大小;并且,比较两个引用时,Rust 会自动去比较它们所指向的底层数据。

所以,只要引用指向的类型实现了 PartialOrd(如整数、浮点数、字符串等),引用之间就能直接比较。

fn main() {
    let number_list = vec![34, 50, 25, 100, 65];

    let mut largest = &number_list[0];

    for number in &number_list {
        if number > largest {
            largest = number;
        }
    }

    println!("The largest number is {largest}");
}

中 if number > largest 改成 *number > *largest 也是可以的。 这就是手动解引用。

如果我真的想比较引用的“内存地址”怎么办?
因为 Rust 默认比较引用是指向的值,如果你在某些极少数的底层场景下,真的想要比较两个变量是不是存放在内存的同一个位置(比较地址大小),你需要把它们转换成裸指针(Raw Pointers):

if (number as *const i32) > (largest as *const i32)

5G NSA的几种形式

NSA就是LTE与NR的双连接,具体有:
EN-DC (4G核心网,4G基站为主站,5G基站为辅) E_UTRAN New Radio-Dual Connectivity
NE-DC (5G核心网, 5G为主,4G为辅助)
NGEN-DC (5G核心网,4G为主, 5G为辅)

用于反汇编联发科基带的ghidra nanomips isa module

原文:https://www.nccgroup.com/research-blog/ghidra-nanomips-isa-module/
原作者:James Chambers

2023年末至2024年初,NCC集团硬件和嵌入式系统业务部门承接了一项任务,对多款智能手机的基带固件进行逆向工程。这其中包括基于nanoMIPS架构的联发科5G基带固件。我们了解到一些针对Ghidra的nanoMIPS模块是私下开发的,当时并没有公开可用的可靠选项,因此我们自行开发了Ghidra的nanoMIPS反汇编器和反编译器模块。

出于(节省)时间的考虑,我们专注于实现在实际基带固件中遇到的功能和指令,而将尚不需要的复杂P-Code指令模拟保留未实现。虽然该模块仍在开发中,但它仍然能够反编译我们分析过的大部分基带固件。结合一些联发科固件中包含的调试符号信息,该模块在逆向工程过程中发挥了重要作用。

在这里,我们将演示如何将联发科基带固件用我们的 nanoMIPS ISA模块加载到 Ghidra 中,来进行分析。

为了分析固件示例,我们查找了可能搭载带5G支持的联发科SoC的手机。一些相对较新的摩托罗拉机型是不错的选择。(这些设备不属于我们的客户合作范围。)

我们在 https://mirrors.lolinet.com/firmware/lenomola/ 上找到了许多 Android 固件镜像,其中包括摩托罗拉 Moto Edge 2022(代号 Tesla)的固件镜像:
https://mirrors.lolinet.com/firmware/lenomola/tesla/official/。
该型号基于联发科 Dimensity 1050(MT6879)SoC。

固件有一些特定于运营商的版本。我们将随机选择
https://mirrors.lolinet.com/firmware/lenomola/2022/tesla/official/TMO/XT2205-1_TESLA_TMO_12_S2STS32.71-118-4-2-6-3_subsidy-TMO_UNI_RSU_QCOM_regulatory-DEFAULT_cid50_CFC.xml.zip

实际的 nanoMIPS 固件位于从ZIP包里提取的md1img.img中

为了提取md1img的文件内容,我们还编写了一些 Kaitai 结构定义,并使用简单的 Python 脚本来运行结构解析,并将不同部分输出到单独的文件中。
ksy Kaitai定义还可用于通过Kaitai IDE以交互方式探索这些文件。

使用选项–outdir 运行 md1_extract.py, 将提取其中包含的文件md1img.img:

$ ./md1_extract.py ../XT2205-1_TESLA_TMO_12_S2STS32.71-118-4-2-6-3_subsidy-TMO_UNI_RSU_QCOM_regulatory-DEFAULT_cid50_CFC/md1img.img --outdir ./md1img_out/
extracting files to: ./md1img_out
md1rom: addr=0x00000000, size=43084864
        extracted to 000_md1rom
cert1md: addr=0x12345678, size=1781
        extracted to 001_cert1md
cert2: addr=0x12345678, size=988
        extracted to 002_cert2
md1drdi: addr=0x00000000, size=12289536
        extracted to 003_md1drdi
cert1md: addr=0x12345678, size=1781
        extracted to 004_cert1md
cert2: addr=0x12345678, size=988
        extracted to 005_cert2
md1dsp: addr=0x00000000, size=6776460
        extracted to 006_md1dsp
cert1md: addr=0x12345678, size=1781
        extracted to 007_cert1md
cert2: addr=0x12345678, size=988
        extracted to 008_cert2
md1_filter: addr=0xffffffff, size=300
        extracted to 009_md1_filter
md1_filter_PLS_PS_ONLY: addr=0xffffffff, size=300
        extracted to 010_md1_filter_PLS_PS_ONLY
md1_filter_1_Moderate: addr=0xffffffff, size=300
        extracted to 011_md1_filter_1_Moderate
md1_filter_2_Standard: addr=0xffffffff, size=300
        extracted to 012_md1_filter_2_Standard
md1_filter_3_Slim: addr=0xffffffff, size=300
        extracted to 013_md1_filter_3_Slim
md1_filter_4_UltraSlim: addr=0xffffffff, size=300
        extracted to 014_md1_filter_4_UltraSlim
md1_filter_LowPowerMonitor: addr=0xffffffff, size=300
        extracted to 015_md1_filter_LowPowerMonitor
md1_emfilter: addr=0xffffffff, size=2252
        extracted to 016_md1_emfilter
md1_dbginfodsp: addr=0xffffffff, size=1635062
        extracted to 017_md1_dbginfodsp
md1_dbginfo: addr=0xffffffff, size=1332720
        extracted to 018_md1_dbginfo
md1_mddbmeta: addr=0xffffffff, size=899538
        extracted to 019_md1_mddbmeta
md1_mddbmetaodb: addr=0xffffffff, size=562654
        extracted to 020_md1_mddbmetaodb
md1_mddb: addr=0xffffffff, size=12280622
        extracted to 021_md1_mddb
md1_mdmlayout: addr=0xffffffff, size=8341403
        extracted to 022_md1_mdmlayout
md1_file_map: addr=0xffffffff, size=889
        extracted to 023_md1_file_map

最相关的文件是:
md1rom是 nanoMIPS 固件映像
md1_file_map 提供更多关于 md1_dbginfo 文件的上下文:它的原始文件名是DbgInfo_NR16.R2.MT6879.TC2.PR1.SP_LENOVO_S0MP1_K6879V1_64_MT6879_NR16_TC2_PR1_SP_V17_P38_03_24_03R_2023_05_19_22_31.xz
md1_dbginfo 是一个 XZ 压缩二进制文件,含有md1rom 的调试信息(包括符号)

提取调试符号

md1_dbginfo是包含符号、文件名以及对应的地址的另一种二进制文件格式。我们将根据md1_file_map来的文件名,对其进行重命名和解压缩:

$ cp 018_md1_dbginfo DbgInfo_NR16.R2.MT6879.TC2.PR1.SP_LENOVO_S0MP1_K6879V1_64_MT6879_NR16_TC2_PR1_SP_V17_P38_03_24_03R_2023_05_19_22_31.xz
$ unxz DbgInfo_NR16.R2.MT6879.TC2.PR1.SP_LENOVO_S0MP1_K6879V1_64_MT6879_NR16_TC2_PR1_SP_V17_P38_03_24_03R_2023_05_19_22_31.xz
$ hexdump DbgInfo_NR16.R2.MT6879.TC2.PR1.SP_LENOVO_S0MP1_K6879V1_64_MT6879_NR16_TC2_PR1_SP_V17_P38_03_24_03R_2023_05_19_22_31 | 头
00000000 43 41 54 49 43 54 4e 52 01 00 00 00 98 34 56 00 |CATICTNR.....4V.|
00000010 43 41 54 49 01 00 00 00 00 00 00 00 4e 52 31 36 |CATI........NR16|
00000020 2e 52 32 2e 4d 54 36 38 37 39 2e 54 43 32 2e 50 |.R2.MT6879.TC2.P|
00000030 52 31 2e 53 50 00 4d 54 36 38 37 39 5f 53 30 30 |R1.SP.MT6879_S00|
00000040 00 4d 54 36 38 37 39 5f 4e 52 31 36 2e 54 43 32 |.MT6879_NR16.TC2|
00000050 2e 50 52 31 2e 53 50 2e 56 31 37 2e 50 33 38 2e |.PR1.SP.V17.P38.|
00000060 30 33 2e 32 34 2e 30 33 52 00 32 30 32 33 2f 30 |03.24.03R.2023/0|
00000070 35 2f 31 39 20 32 32 3a 33 31 00 73 00 00 00 2b |5/19 22:31.s...+|
00000080 ed 53 00 49 4e 54 5f 56 65 63 74 6f 72 73 00 4c |.S.INT_Vectors.L|
00000090 08 00 00 54 08 00 00 62 72 6f 6d 5f 65 78 74 5f |...T...brom_ext_|

为了从调试信息文件中提取信息,我们制作了另一个 Kaitai 定义和脚本,来提取符号并以与 Ghidra 脚本ImportSymbolsScript.py兼容的文本格式输出它们:

$ ./mtk_dbg_extract.py md1img_out/DbgInfo_NR16.R2.MT6879.TC2.PR1.SP_LENOVO_S0MP1_K6879V1_64_MT6879_NR16_TC2_PR1_SP_V17_P38_03_24_03R_2023_05_19_22_31 | tee dbg_symbols.txt
INT_Vectors 0x0000084c l
brom_ext_main 0x00000860 l
INT_SetPLL_Gen98 0x00000866 l
PLL_Set_CLK_To_26M 0x000009a2 l
PLL_MD_Pll_Init 0x000009da l
INT_SetPLL 0x000009dc l
INT_Initialize_Phase1 0x027b5c80 l
INT_Initialize_Phase2 0x027b617c l
init_cm 0x027b6384 l
init_cm_wt 0x027b641e l
...

(目前脚本设置为仅输出标签定义而不是函数定义,因为不知道所有符号是否都用于函数。)

安装扩展

首先,我们需要为 Ghidra 安装 nanoMIPS 模块。在 Ghidra 主窗口中,前往“File > Install Extensions”,
点击“Add Extension”加号按钮,然后选择模块的 Zip 文件(例如ghidra_11.0.3_PUBLIC_20240424_nanomips.zip)。
然后重启 Ghidra。

初始加载
加载 md1rom 为原始二进制镜像(raw binary image)。
从md1img.img的解压目录中选择000_md1rom,并保留“Raw Binary”作为格式。
对于语言,点击“Browser”省略号,并使用过滤器 找到小端 32 位 nanoMIPS 选项 (nanomips:LE:32:default ),然后点击“确定”。

我们将在偏移量 0 处加载image,因此无需其他选项。再次单击“确定”即可加载原始二进制文件。

当 Ghidra 询问您是否要进行初始自动分析时,选择“否”。我们必须首先设置镜像内存地址空间0x90000000。

内存映射

打开“内存映射”窗口,然后单击“添加内存块”的加号。

我们将新块命名为“mirror”,将起始地址设置为ram:90000000,长度与基础映像“ram”块的长度(0x2916c40)匹配,权限为读取和执行,并将“块类型”设置为“字节映射”,源地址为 0,映射率为 1:1。

还要将原始“ram”块的权限更改为仅读取和执行。保存内存映射更改并关闭“内存映射”窗口。

请注意,此内存映射是不完整的;它只是使反汇编工作所需的最小设置。

调试符号

接下来,我们将加载调试符号。打开脚本管理器窗口并搜索ImportSymbolsScript.py。运行脚本并选择mtk_dbg_extract.py之前生成的文本文件 ( dbg_symbols.txt)。这将创建一堆标签,其中大部分位于镜像地址空间中。

反汇编

现在我们可以开始反汇编了。地址 0 处有一条跳转指令,可以引导我们开始,因此只需选中地址 0 处的字节,然后按“d”键或右键单击并选择“反汇编”即可。借助调试符号,您可能会注意到该指令跳转到了INT_Initialize_Phase1相应的函数。
基于流程的反汇编现在将开始发现一堆代码。初始反汇编可能需要几分钟才能完成。

然后,我们可以通过“分析 > 自动分析…”运行常规的自动分析。这应该也能发现更多代码,并需要几分钟的时间进行反汇编和反编译。
我们发现,“Non-Returning Functions”分析器在这些固件映像中使用默认配置会产生许多误报,从而扰乱代码流,因此我们建议在初始分析时禁用它。一次性“Decompiler Parameter ID”分析器是下一步运行的一个很好的选择,可以更好地检测函数输入类型。

结论

尽管该模块仍在开发中,但其结果已经可用于分析,并使我们能够对基带处理器中的一些关键功能进行逆向工程。

nanoMIPS Ghidra 模块和联发科二进制文件解包器可以在我们的 GitHub 上找到:

https://github.com/nccgroup/ghidra-nanomips
https://github.com/nccgroup/mtk_bp

微信分享如何启动指定的profile

https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/app/ResolverActivity.java

com.android.internal.app.ResolverActivity的safelyStartActivityInternal

protected void safelyStartActivityInternal(
TargetInfo cti, UserHandle user, @Nullable Bundle options)

UserHandle.of(user_id)
user_id = user_handle.getIdentifier();
————-
com.miui.xspace.utils.XSpaceResolverActivityHelper
private void forward(int userId)

frida新的build方法

debian系统

1. 安装系统依赖
build-essential
git
lib32stdc++-14-dev
libc6-dev-i386

2. 安装nodejs
/etc/apt/sources.list.d/nodesource.sources

Types: deb
URIs: https://deb.nodesource.com/node_23.x/
Suites: nodistro
Components: main
Signed-By: /usr/share/keyrings/nodesource.gpg

apt install nodejs

3. 设置环境变量
export C_INCLUDE_PATH=/usr/include/python3.13

4. 获取源代码
git clone https://github.com/frida/frida.git

5. 编译python库,脚本
./configure –prefix /home/softsim/frida
make
make install

6. 编译android64 server
mkdir build-android
export ANDROID_NDK_ROOT=/home/softsim/Android/Sdk/ndk/25.2.9519653
../frida/configure –host=android-arm64 –prefix /home/softsim/frida-android64
make
make install

7. 编译linux_x64 server
mkdir build-x64
cd build_x64
../frida/configure –host=linux-x86_64 –prefix /home/softsim/frida_x64
make
make install

Qualcomm Baseband Research

https://blog.rickmark.me/untitled/

sbl1.mbn – Secondary Bootloader (after ROM PBL)
qdsp6sw.mbn – Qualcomm Hexagon Digital Signal Processor (non-ARM core)
tz.mbn – Qualcomm TrustZone Implementation – QSEE
hyp.mbn – Qualcomm Hypervisor Execution Environment – QHEE – EL2
xbl_cfg.mbn – For XBL (eXtensible Boot Loader) or EFI based SPL signed static data
restoresbl1.mbn – Secondary program loader (bootloader) for baseband recovery
acdb.mbn – Accessory Calibration Database (seems to be initial)
apps.mbn – Userland baseband applications
rpm.mbn – Rollback prevention manager
wdt.mbn – Watchdog Timer
mba.mbn – QURT – Qualcomm Realtime OS Kernel image

MBN Signature Format

Contains a C struct styled header, followed by hashes, a signature and a certificate chain.

MBNs are ill-designed because the ELF header contains the offset to the signature region, which signs the ELF header
creating a circular dependency.

Header Region

// Likely depends on hash type - samples found stated PK algorithm scep384r1 having a signature size of 384 - deterministic noncing?
// does this lead to a potential leak of private key with double nonce values?
typedef struct {
  char* hash[HASH_TYPE_SIZE]; // Unfortuantly they used all zeros to encode an empty region instead of hash of zeros...
                              // This seems to always be true of the signature area (b01) but also of other regions?
} mbn_hash_row_t;

typedef enum {
  kSHA2_384 = 0x06;
} mbn_hash_type_t;

typedef struct {
  uint32_t hash_rows;         // Number of hash rows - samples with 0 have hashes but no signature... and 0xFFFFFFFF for
                              // pk_hash.  It also has hash rows, perhaps its a problem via multiple verification paths?
  mbn_hash_type_t hash_type;  // 6 - SHA2-384?
  uint32_t = 0
  uint32_t = 0
  uint32_t hash_and_signature_size; // Little endian - data following header and extra
  uint32_t hash_size; // size in bytes of hash type row size * rows - signature follows
  uint32_t pk_hash_one? = 0xFFFFFFFF / 0xA803708F
  uint32_t signature_size; // Size of ASN.1 signature following hash list
  uint32_t pk_hash_two? = 0xFFFFFFFF / 0xA803708F // Usually matches pk_hash_one
  uint32_t some_size;  // Some header item size or possibly align value?
  uint32_t = 0;
  uint32_t extra_size; // Seems to be 0x78 bytes long... 64bit extension?
  char* extra[extra_size];
  mbn_hash_row_t hashes[hash_rows];
} mbn_header_t;

typedef struct {

rust字节数组

array和slice的概念

数组(array)是一组拥有相同类型 T 的对象的集合,在内存中是连续存储的。数组使用中括号 [] 来创建,且它们的大小在编译时会被确定。数组的类型标记为 [T; length]T 为元素类型,length 表示数组大小)。

切片(slice)类型和数组类似,但其大小在编译时是不确定的。相反,切片是一个双字对象(two-word object),第一个字是一个指向数据的指针,第二个字是切片的长度。这个 “字” 的宽度和 usize 相同,由处理器架构决定,比如在 x86-64 平台上就是 64 位。slice 可以用来借用数组的一部分。slice 的类型标记为 &[T]

字节数组的几种类型:

(一)      [u8; N](固定大小的字节数组)
这是一个固定长度的数组,长度 N 在编译时确定。
存储在栈上(stack),如果数组过大可能导致栈溢出。
拥有数据的所有权。
大小无法在运行时改变, 如果需要改变,只能释放了再新建。
访问时可以使用 & 获取切片(&[u8])

(二)   &[u8](字节切片 引用)
动态大小,存储在堆上或栈上,通常是借用(reference)。
可通过 as_ref()、deref() 或 slice::from_ref() 从数组转换。
它是一个对字节序列的不可变引用,可以指向[u8; N] 或Vec<u8> 等的一部分
不拥有数据,仅借用;长度在运行时确定。

切片本身 不拥有 任何数据。它只是指向已存在字节数据的指针和长度。数据的所有权属于切片所引用的原始数据。
切片的大小在运行时确定,由其指向的数据的长度决定。

(三)   &mut [u8](可变字节切片)
和 &[u8] 类似,但允许修改数据

(四)   Vec(动态字节数组)
可变长,存储在堆上(heap)。
适用于需要增长或缩短的字节数据
拥有数据的所有权,可以动态调整大小
允许 push、resize、extend 等操作。
通过 push, pop, insert, remove 等方法进行增删元素

(五)  Box<[u8]>(堆分配的字节数组)
固定长度的堆分配数组,与 Vec 类似但不可变长。
适用于数据不需要增长的情况,但仍希望存储在堆上。
let boxed: Box<[u8]> = vec![1, 2, 3, 4].into_boxed_slice();
拥有所有权,在堆上分配,大小固定但可以在运行时创建

(六)   Cow<[u8]>(惰性克隆的字节数组)
Cow(Copy on Write,写时复制)适用于既可能是借用的(&[u8])也可能是拥有的(Vec)数据。
适用于优化性能,避免不必要的复制,只有在需要修改时才会克隆数据。

(七) [u8] 未定大小的字节切片
这是一个抽象的字节切片类型,通常在泛型或 trait 定义中使用。
无法直接实例化,仅作为类型参数出现。
是一个视图(view)而非拥有数据的类型

(八) String和&str
用于文本字符串,以UTF-8编码的字节。本质上也是字节序列。
String拥有数据, &str是一个切片引用。

在某些情况下,你可能会将 String 或 &str 视为字节数组来处理,例如在处理 ASCII 文本或进行底层字符串操作时。但要注意,它们强制 UTF-8 编码,可能不适合处理任意二进制数据。

转换:
[u8; N] 可以转换为 &[u8] 或 &mut [u8](用 &符号 借用)
&[u8] 可以转换为 Vec( 用.to_vec()复制为Vec<u8>)
Vec 可以转换为 Box<[u8]>(比如上面的介绍的into_boxed_slice())
&[u8] 或 Vec 可以转换为 Cow<[u8]>
Vec<u8> 可以通过 .as_slice() 转为 &[u8]
&[u8] 转化 &[u8; N] , 用 try_into()

注意事项:
&[u8] 和 Box<[u8]> 是不可变的(除非使用内部可变性如 Cell 或 RefCell)
&[u8] 和 &mut [u8] 长度由引用的数据决定