时间从来不语,却回答了很多问题


c++编译后会给函数签名加上很多特有的修饰,比如bool ReqGetGuildUserList(long)将会被编译成:

1
?ReqGetGuildUserList@@YA_NJ@Z

Dependency Walker这个工具可以看的很清楚的。

     Dependency Walker工具一般是用来查看dll或者exe的依赖项的,这样就可以在软件发布的时候避免漏掉某些dll,当然对于动态加载的dll是没有办法的。但其中的Undecorate C++ Functions功能也甚是好用。

编译后的dll导出签名格式

阅读此文


DASCTF,easyre签到题,ASPack,脱壳后找到关键函数

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int __cdecl sub_401771(char *Str)
{
int v2[50]; // [esp+1Ch] [ebp-DCh] BYREF
int v3; // [esp+E4h] [ebp-14h]
int j; // [esp+E8h] [ebp-10h]
int i; // [esp+ECh] [ebp-Ch]

v3 = strlen(Str);
sub_401500();
sub_40152B();
sub_401593();
sub_401619(Str, v3);
for ( i = 0; i < v3; ++i )
byte_492A60[i] = (LOBYTE(dword_492940[i]) ^ Str[i]) + 71;
memset(v2, 0, sizeof(v2));
v2[0] = -61;
v2[1] = -128;
v2[2] = -43;
v2[3] = -14;
v2[4] = -101;
v2[5] = 48;
v2[6] = 11;
v2[7] = -76;
v2[8] = 85;
v2[9] = -34;
v2[10] = 34;
v2[11] = -125;
v2[12] = 47;
v2[13] = -105;
v2[14] = -72;
v2[15] = 32;
v2[16] = 29;
v2[17] = 116;
v2[18] = -47;
v2[19] = 1;
v2[20] = 115;
v2[21] = 26;
v2[22] = -78;
v2[23] = -56;
v2[24] = -59;
v2[25] = 116;
v2[26] = -64;
v2[27] = 91;
v2[28] = -9;
v2[29] = 15;
v2[30] = -45;
v2[31] = 1;
v2[32] = 85;
v2[33] = -78;
v2[34] = -92;
v2[35] = -82;
v2[36] = 123;
v2[37] = -84;
v2[38] = 92;
v2[39] = 86;
v2[40] = -68;
v2[41] = 35;
for ( j = 0; j <= 41; ++j )
{
if ( v2[j] != byte_492A60[j] )
exit(0);
}
return sub_47BAB0((int)off_488140, aRight);
}

可以看到逻辑很简单,但是这里有int和char的强转问题,直接python逆向,会出现超出有符号char类型范围的问题。可以看到强转的汇编位置:

所以编写脚本的时候必须舍弃高位,低8位要和0x7F相与

wp

阅读此文


Intro

现在网络上貌似没有,出于学习与兴趣,对某校园通信进行分析,仅供学习。

抓包工具

使用fiddler4,测试机使用代理连接并配置证书,此处不做讲解

登陆方式

某校园提供多种登陆方式,包括微信支付宝等。这里我们研究下密码登陆以及短信验证码登陆。

首先我们选择密码登陆,界面大概是这样子:

阅读此文


post @ 2022-03-20

函数的调用约定描述了执行函数时返回地址和参数的出入栈规律。不同公司开发的C语言编译器都有各自的函数调用约定,而且这些调用约定的差异性很大。随着IBM兼容机对市场进行洗牌后,微软操作系统和编程工具占据了统治地位。除微软之外,仍有零星的几家公司和开源项目GNU C在维护自己的调用约定。下面将介绍几款比较流行的函数调用约定。

x86/x86_64

❏ stdcall调用约定
■ 在调用函数时,参数将按照从右向左的顺序依次压入栈中,例如下面的function函数,其参数入栈顺序依次是second、first:
​​​​​​​​​​​​​​​​int function(int first, int second)​​
■ 函数的栈平衡操作(参数出栈操作)是由被调用函数完成的。通过代码retn x可在函数返回时从栈中弹出x字节的数据。当CPU执行RET指令时,处理器会自动将栈指针寄存器ESP向上移动x个字节,来模拟栈的弹出操作。例如上面的function函数,当function函数返回时,它会执行该指令把参数second和first从栈中弹出来,再到返回地址处继续执行。
■ 在函数的编译过程中,编译器会在函数名前用下划线修饰,其后用符号@修饰,并加上入栈的字节数,因此函数function最终会被编译为_function@8。

❏ cdecl调用约定
■ cdecl调用约定的参数压栈顺序与stdcall相同,皆是按照从右向左的顺序将参数压入栈中。
■ 函数的栈平衡操作是由调用函数完成的,这点与stdcall恰恰相反。stdcall调用约定使用代码retn x平衡栈,而cdecl调用约定则通常会借助代码leave、pop或向上移动栈指针等方法来平衡栈。
■ 每个函数调用者都含有平衡栈的代码,因此编译生成的可执行文件会较stdcall调用约定生成的文件大。
cdecl是GNU C编译器的默认调用约定。但GNU C在64位系统环境下,却使用寄存器作为函数参数的传递方式。函数调用者按照从左向右的顺序依次将前6个整型参数放在通用寄存器RDI、RSI、RDX、RCX、R8和R9中;同时,寄存器XMM0~XMM7用来保存浮点变量,而RAX寄存器则用于保存函数的返回值,函数调用者负责平衡栈。

❏ fastcall调用约定
■ fastcall调用约定要求函数参数尽可能使用通用寄存器ECX和EDX来传递参数,通常是前两个int类型的参数或较小的参数,剩余参数再按照从右向左的顺序逐个压入栈中。
■ 函数的栈平衡操作由被调用函数负责完成。
除此之外,还有很多调用约定,如thiscall、nakedcall、pascal等,有兴趣的读者可以自行研究。

ARM64

ARM64 调用约定
- 参数在 x0-x7 寄存器中传递,其余在堆栈中传递
- ret 命令用于返回 Link 寄存器中的地址(默认值为 x30)
- 函数的返回值存储在 x0 或 x0+x1 中,具体取决于它是 64 位还是 128 位
- x8 是间接结果寄存器,用于传递间接结果的地址位置,例如函数返回一个大结构的地方
- 使用 B 操作码跳转到函数。
- 带链接分支 (BL) 将下一条指令的地址(在 BL 之后)复制到分支前的链接寄存器 (x30)
因此,BL 用于子程序调用
BR调用用于分支注册,例如br x8
BLR 代码用于跳转寄存器并将下一条指令的地址(在 BL 之后)存储到链接寄存器(x30)中

阅读此文


goroutine运行

只需在调用前加一个go关键字。例如:

1
2
3
4
5
6
7
8
9
10
11

func main() {
// go 关键字启用goroutine
go sleepyGopher() // 分支线路
time.Sleep(4 * time.Second) // 主线路
}

func sleepyGopher() {
time.Sleep(3 * time.Second)
fmt.Println(" ...snore... ")
}

每次使用go关键字都会产生一个新的goroutine。

表面goroutine似乎在同时运行,事实上由于处理器使用分时技术,并没有真的同时运行。

通道 channel

通道可以在多个goroutine之间安全的传值。

阅读此文


为什么要学Rust

  • Rust是一种令人兴奋的新编程语言,它可以让每个人编写可靠且高效的软件。
  • 它可以用来替换C/C++,Rust拥有和他们同样的性能,但是很多常见的bug在编译时就可以被消灭
  • Rust是一种通用的编程语言,但是它有以下优点:
    • 运行速度快,无需GC
    • 内存安全
    • 更好地利用多处理器,无所畏惧的并发
    • 易于维护、调试、代码安全高效

Rust特别擅长的领域

  • 高性能Web Service
  • WebAssembly
  • 命令行工具
  • 网络编程
  • 嵌入式设备
  • 系统编程

Rust的用户和案例

  • Google:新操作系统 Fuschia,其中 Rust 代码量大约占30%
  • Amazon:基于 Linux 开发的直接可以在裸机、虚拟机上运行容器的操作系统
  • System76:纯 Rust 开发了下一代安全操作系统 Redox
  • 蚂蚁金服:库操作系统 Occlum
  • 微软:正在使用 Rust 重写 Windows 系统中的一些低级组件
  • 微软:WinRT/Rust 项目
  • Linus 之前已经同意使用 Rust 为 Linux 贡献代码

本课程学习记录参考 Rust 权威指南,视频教程作者:杨旭,微软 MVP

阅读此文


样例源代码如下:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use rand::Rng;
use std::cmp::Ordering;
use std::io;

fn main() {
println!("猜数游戏!"); // 这不是一个函数,而是宏

// 下面定义了一个不可变变量,rust是一个强变量类型语言,
// 编译器会自动匹配类型创建变量。
// 赋值语句右边调用了rand这个crate中的函数,生成[1, 101)中的一个u32变量
let secret_number = rand::thread_rng().gen_range(1, 101);
// println!("神秘数字是:{}", secret_number);


loop {
println!("猜测一个数");

// mut关键字:代表变量可变
// String命名空间中的new函数。返回一个字符串变量
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("无法读取行");
// shadow

// 变量右边冒号声明变量类型,parse函数实现类型转换,expect捕获异常
// let guess: u32 = guess.trim().parse().expect("请输入一个数字!");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
// 下划线代表不关心里面的信息
Err(_) => {
println!("请输入一个数!");
continue;
},
};
println!("你猜的数是:{}", guess);

// cmp进行比较,使用match进行模式匹配
// 每一个分支都是一个arm
match guess.cmp(&secret_number) {
Ordering::Less => println!("太小了!"), // arm
Ordering::Greater => println!("太大了!"),
Ordering::Equal => {
println!("你赢了!");
break;
}
}
}

}
阅读此文


post @ 2022-02-27

python编写的极简Caot聊天室,所有代码不超过200行,多人在线匿名聊天

https://github.com/YinglongCao/Caot

阅读此文


post @ 2022-01-22

重新安装了python,安装yara后运行插件报错。

解决:卸载yara,安装yara-python

阅读此文


注:此插件原版很久没更新,熊猫修改版:

https://github.com/P4nda0s/LazyIDA

原版LazyIDA github地址:

https://github.com/L4ys/LazyIDA

之前在7.0Mac版上使用LazyIDA插件正常,然后今天在Windows下用IDA时发现LazyIDA插件加载错误,显示第8行错误:cannot import name ‘qapplication’ from ‘pyqt5.qt。搜索一番修改无果。

于是打开LazyIDA,发现QApplication导入只在前两个函数:复制和粘贴处被使用。

1
2
3
4
5
6
7
8
from PyQt5.Qt import QApplication  # 导入错误


def copy_to_clip(data):
QApplication.clipboard().setText(data)

def clip_text():
return QApplication.clipboard().text()
阅读此文
⬆︎TOP