羊城杯2023初赛复现
羊城杯2023初赛复现shellcode通过逆向分析一下,发现是存在一个16字节的输入,会将该输入当成代码去执行,并且限制在了0x4e到0x5F之间
1234567891011121314151617 memset(s, 0, 16uLL); puts("[5] ======== Input Your P0P Code ========"); for ( buf = s; buf; buf = (buf + 1) ) { read(0, buf, 1uLL); if ( (buf - s) >> 4 > 0 ) break; } while ( *v4 && *v4 > 0x4E && *v4 <= 0x5F ) { ++v2; v4 = (v4 + 1); }.text:00000000000014EE 48 8B 45 D8 mov rax, [rbp+ ...
编译内核驱动
编译内核驱动编译驱动这里我们来尝试编译一个驱动模块。驱动代码如下
123456789101112131415#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>MODULE_LICENSE("Dual BSD/GPL");static int ko_test_init(void) { printk("This is a test ko!\n"); return 0;}static void ko_test_exit(void) { printk("Bye Bye~\n");}module_init(ko_test_init);module_exit(ko_test_exit);
Makefile 文件如下
123456789obj-m += ko_test.oKDIR =/home/iromise/dev/kernel/linux-5.4. ...
缓冲区溢出原理
缓冲区溢出原理 缓冲区是程序运行时计算机内存中的一块连续的地址空间,它用于保存给定类型的数 据。在一些高级语言的函数调用中,缓冲区是在堆栈上进行分配的。堆栈是一个后进先出的 队列,它的生长方向与内存的生长方向正好相反。具体如图所示
在正常情况下,处理器在函数调用时,将函数的参数、返回地址(即进行函数调用的那 条指令的下一条指令的地址)及基址寄存器EBP(该寄存器存储的内存地址为函数在参数和 变量压栈之前的内存地址)压入堆栈中,然后把当前的栈指针(ESP)作为新的基地址。如果 函数有局部变量,则函数会把堆栈指针ESP 减去某个值,为需要的动态局部变量腾出所需的内存空间,函数内使用的缓冲区就分配在腾出的这段内存空间上。函数返回时,弹出EBP 恢复堆栈到函数调用前的地址,弹出返回地址到EIP 以继续执行原程序。假设程序从攻击者处接收一长度超过缓冲区长度的字符串, 则会出现安全漏洞。由于堆 栈的生长方向与内存的生长方向正好相反, 如果接收的是超长字符串,EBP 和EIP 的值就 有可能被覆盖。一般情况下,会导致程序运行失败,但如果覆盖EIP 的值刚好是攻击代码的 内存地址,从而 ...
给指针赋值整数
给指针赋值整数1234567891011121314151617181920//1#include <stdio.h>int main(){ int *ptr; int n = 5; ptr = &n;//&n就是已分配内存的(int型)的地址 printf("%d",*ptr);}//2#include <stdio.h>int main(){ int *ptr; *ptr = 5; printf("%d",*ptr);}
通过上述例子:我们知道了指针变量不能直接赋值。因为创建一个指针时,系统只分配了存储指针本身的内存,并未分配存储数据的内存,因此在用指针之前必须用已分配的地址初始化它。以上述为例2中的意思就是把5存储在ptr所指向的位置,但是pt没有初始化,其值是一个随机值,所以不知道5将存储在何处。程序会崩溃.
经典蓝牙、低功耗蓝牙、蓝牙Mesh
经典蓝牙、低功耗蓝牙、蓝牙Mesh同样是蓝牙技术,为什么有经典蓝牙、低功耗蓝牙之分,蓝牙Mesh又是什么回事?
1、蓝牙技术发展简史网上关于蓝牙技术的发展介绍已经很多了,这里就不再过多介绍了,可以看下面这张图简单了解下。
蓝牙技术发展史(截止2019)
蓝牙技术的官方组织是蓝牙技术联盟(Bluetooth special interest group,简称Bluetooth SIG),目前蓝牙协议已经发展到了蓝牙5.2(2020.5),如下是蓝牙技术的官方网站。
蓝牙 技术网站 |官方网站 蓝牙 技术。www.bluetooth.com/zh-cn/
对蓝牙协议比较感兴趣,并且英文比较好的话,可以直接看官方最新的蓝牙5.2文档:
https://3pl46c46ctx02p7rzdsvsg21-wpengine.netdna-ssl.com/wp-content/uploads/2020/01/Bluetooth_5.2_Feature_Overview.pdf3pl46c46ctx02p7rzdsvsg21-wpengine.netdna-ssl.com/wp-conte ...
线程,进程,协程的区别
线程,进程,协程的区别线程、进程和协程是程序执行的不同抽象,每种方式在操作系统中的资源管理、执行方式和用途上都有所不同。下面详细解释每一个概念及其之间的区别:
1. 进程(Process)
定义:进程是操作系统进行资源分配和调度的基本单位。它是一个程序的实例,具有独立的地址空间。每个进程至少有一个线程(主线程),并且可以包含多个线程。
特点
:
每个进程有自己独立的内存空间和系统资源(如文件句柄和设备)。
进程间通信(IPC)需要操作系统提供的特殊机制,如管道、消息队列、共享内存等。
上下文切换成本高,因为涉及到完整的内存空间和执行状态的保存与恢复。
2. 线程(Thread)
定义:线程是进程中的实际运行单位,是操作系统进行CPU调度的基本单位。一个进程中可以包含多个线程,它们共享进程的内存空间和资源。
特点
:
线程间共享同一进程内的内存空间和资源,如文件句柄和其他系统资源。
线程间的通信和同步相对容易,可以直接通过读写共享内存来完成。
上下文切换成本低于进程,因为线程共享大部分资源,切换时只需保存和恢复少量寄存器和栈信息。
3. 协程(Coroutine)
定 ...
线程间的通信方式
线程间的通信方式线程间通信(Inter-Thread Communication, ITC)是指同一进程内的不同线程之间进行数据交换和状态同步的机制。由于所有线程共享同一进程的内存空间,线程间通信比进程间通信更为高效和直接。以下是一些常见的线程间通信方式:
共享内存:
线程可以直接访问同一进程中的共享数据。由于线程共享同一地址空间,这使得共享内存成为线程间通信的最快方式。使用共享内存时,通常需要通过同步机制来防止数据冲突和竞态条件。
互斥锁(Mutexes):
用来确保同时只有一个线程可以访问特定的数据段。互斥锁帮助防止所谓的“竞态条件”,这是多个线程尝试同时读写共享数据时可能出现的问题。
信号量(Semaphores):
和互斥锁类似,信号量是一个更高级的同步机制,用于控制对共享资源的访问。不同于互斥锁只允许一个线程访问资源,信号量可以允许多个线程根据信号量的计数值访问共享资源。
条件变量(Condition Variables):
通常与互斥锁结合使用,条件变量允许线程在某些条件未满足时挂起,等待条件满足时被唤醒。这种机制常用于线程间的事件通知和等待。
事件(Ev ...
系统调用
系统调用系统调用(system calls), Linux内核, GNU C库(glibc).
在电脑中,系统调用(英语:system call),指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。系统调用提供用户程序与操作系统之间的接口。大多数系统交互式操作需求在内核态执行。如设备IO操作或者进程间通信。
用户空间(用户态)和内核空间(内核态)操作系统的进程空间可分为用户空间和内核空间,它们需要不同的执行权限。其中系统调用运行在内核空间。
库函数系统调用和普通库函数调用非常相似,只是系统调用由操作系统内核提供,运行于内核核心态,而普通的库函数调用由函数库或用户自己提供,运行于用户态。
典型实现(Linux)Linux 在x86上的系统调用通过 int 80h 实现,用系统调用号来区分入口函数。操作系统实现系统调用的基本过程是:
应用程序调用库函数(API);
API 将系统调用号存入 EAX,然后通过中断调用使系统进入内核态;
内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用);
系统调用完成相应功能,将返回值存入 EAX,返回到中断处理函数;
中断处 ...
类型,运算符与表达式
类型,运算符与表达式1.变量名
变量名以下划线“_”和字母开头,是由字母和数数字组成的序列,下划线被当成字母。
变量不能使用保留的关键字“if,else,int等。
选择的变量名要能尽量表达变量的用途。
2.数据类型及长度
C语言只提供4种基本数据类型
char 字符型,占用__一个字节__。
int 整型,通常反映了__所用机器中整数的最自然长度__。
float 单精度浮点型。
double 双精度浮点型。
__short__与__long__两个限定符用于限定整型(int)。
(声明中关键字_int_可以省略)
long 类型通常为32位,short类型通常为16位,int类型可以为16位或32位。(根据各个硬件特性不同,长度也不同,但至少int类型长度不得大于long,不得小于short。
类型限定符__signed__和__unsigned__可用于限定char类型或任何整型。
unsigned类型的数总是正值或零,并遵守[^算术模二]定律,不带限定符的char类型对象是否带符号则取决于具体机器,但可打印字符总是正值。
long duoble 类型表 ...
第二章:编译和链接_3_4
第二章:编译和链接_3_42.3 链接器的年龄比编译器长
程序并不是一写好久永远不变的,它会经常被修改。比如我们在第一条指令之后,第五条指令之前插入了一条或多条指令,那么第五条指令后面的的指令的位置也会相应的往后移动,当程序修改的时候,这些位置都要重新计算,十分繁琐又耗时,并且容易出错。这种重新计算各个目标地址的过程叫做 重定位
于是 符号这个概念随着汇编语言的普及迅速的被使用,他可以用来表示一个地址,这个地址可能是一段程序的起始地址,也可以是一个变量的起始地址。
2.4 模块拼装——静态链接程序设计模块化是人们一直在追求的目标,因为当一个系统十分复杂的时候,我们不得不将一个复杂的系统逐步分割成小的系统以达到各个突破的目的。
一个复杂的软件也是如此,人们把每个源代码模块独立的编译,然后按照须要将他们”组装”起来,这个组装模块的过程就是 链接。链接的主要内容就是把各个模块之间相互引用的部分都处理好,使得各个模块能够正确地衔接。
链接的过程主要包括了 地址和空间分配,符号决议,和重定位等这些步骤。
最基本的静态链接就是将源代码经过编译器编译成 目标文件,目标文件和 库(Library)一 ...



