Aha.
post @ 2022-12-01

X86

在已经学习过inter汇编相关知识的情况下,学习at&t语法并不困难,毕竟最困难的部分已经过去了。

为什么会有两种语法的x86的汇编语言?

汇编语言这个东西本身就和芯片架构高度绑定,其本身就是机器码的助记符,而x86架构的芯片原本就是intel研制的。

所以这个问题可以转化为,为什么at&t要在已有intel语法的基础上再设计一套新语法?

c语言是大名鼎鼎的贝尔实验室发明的,还有UNIX OS,而贝尔实验室属于AT&T,从四五十年前到现在,跑UNIX的服务器很大一部分使用的是非intel x86 CPU,人家好像也根本就不怎么鸟intel编译器。

直到PC的普及。

然后免费的linux出现了,使个人电脑可以使用类UNIX操作系统。虽说比不上windows,但还是有一部分市场。而linux等类UNIX的官方语言就是C语言。这个时候,AT&T就要考虑如何在x86上把C语言编译成能执行的机器码。

至于at&t为什么没有直接采用intel的语法,倒是有些许说法,有的说使intel申请了专利balabala,也有说at&t还是看不上intel的语法,打算新写一种更通用的语法(以后可以应用在别的芯片上),还可能以上影响都有。

那么,具体的区别呢?

Read More
post @ 2022-10-31

前言

前段时间之前那个服务器到期了,一直没管,博客也是,一直没更,说得倒是挺忙的,但其实也没做什么事。每天这样无意义的忙碌,过了好长一段时间。也想记录一些东西的,坐在电脑前却也不知道该干嘛了~~

后面,团队的事就交给师弟师妹了,我也该滚去做些自己的事。

前置知识

个人博客=个人服务器+git+nginx+hexo

首先要有一台服务器(我的是ubuntu),我的本地PC是ubuntu(用子系统和虚拟机也是一样的,用于本地环境的搭建)

hexo环境搭建在本地。

选用hexo,因为他是静态的,可以避免很多安全问题,其次就是比较成熟,且有很多开源的主题,可以DIY

nginx服务器配置在服务器。

用自己的服务器作为博客环境而不是github,主要是我考虑github有时在国内比较玄学的延迟,其次也是为了把上次搭博客没有记录的记录并复现一下

Read More
post @ 2022-06-19

https://codeantenna.com/a/QnTmjbAZo5

https://www.freebuf.com/articles/system/203302.html

fuzz是什么?fuzz是模糊测试,模糊测试是什么?模糊测试是一种软件测试技术?软件测试技术是什么……

但是,即使同为fuzz,因为技术不同,fuzz也分几种。

这篇讲afl-fuzz

afl的特点

afl的安装

源码安装

github源码安装

https://github.com/google/AFL.git

Read More
post @ 2022-06-19

前言

第一次遇见由可视化字符串组成的shellcode视在mrctf2020的一道题里面,当只是大概知道怎么回事就没管过它了。后来在ciscn2022的初赛又遇见同类型题目,想用之前用过的shellcode去套,发现不行,生草了很久最后去蹭了一个可用的shellcode

正文

shellcode一般是指一段已经编辑好的execve函数(提权)的二进制内容(赋值各寄存器,call系统调用)。

在pwntools里可以用shellcraft.sh(),但是这个可能有点长(有时候会超出长度限制)

当然,还有一些祖传代码

1
2
3
4
5
6
7
8
9
10
11
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"
#x64


shellcode=""
shellcode += "\x31\xf6\x48\xbb\x2f\x62\x69\x6e"
shellcode += "\x2f\x2f\x73\x68\x56\x53\x54\x5f"
shellcode += "\x6a\x3b\x58\x31\xd2\x0f\x05"
#x86

但是,这些shellcode如果转化成字符输入大多数会包含一些不可打印字符。而实际情况又经常会发生这种要求输入可见字符。

git clone https://github.com/TaQini/alpha3

Read More
post @ 2022-05-17

pexels-oleg-magni-890570


前记:

其实house系列在CTF中基本上已经绝迹了,除了一些面向新手的pwn题,很少会出现。但这个house_of_orange其实还是时常有出现,这个名字的由来是2016年hitcon的比赛有一道题就叫house_of_orange,然后由此衍生的一系列类似题,是感觉应该是它衔接了普通堆题和IO_FILE结构体。还是有些出题人钟爱于他(以下简称为orange)

题目:house_of_orange

  • 一个全局变量chunks限定同时存在三个堆块。

  • 有add,edit,show,但是没有free操作。

  • 对edit的size没有校验,有一个溢出。

    image-20220519095634447

如果之前有看一些orange的说明,我们其实可以知道,当我们要申请的chunk大于top_chunk时,ptmalloc会将top_chunk放进unsorted_bin,同时增长sbrk。

此操作就相当于free操作,虽然我们之前其实并没有利用过top_chunk。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x5603f4d5e000
Size: 0x21

Allocated chunk | PREV_INUSE
Addr: 0x5603f4d5e020
Size: 0x41

Allocated chunk | PREV_INUSE
Addr: 0x5603f4d5e060
Size: 0x21

Top chunk | PREV_INUSE
Addr: 0x5603f4d5e080
Size: 0xf81

1
2
3
4
unsortedbin
all: 0x5603f4d5e0c0 —▸ 0x7f96a98deb78 (main_arena+88) ◂— 0x5603f4d5e0c0
smallbins

Read More
post @ 2022-04-24

这一篇开始复习tcache

Tcache是glibc2.27后新增加的一种,结构体

1
2
3
4
5
6
/* We overlay this structure on the user-data portion of a chunk when
the chunk is stored in the per-thread cache. */
typedef struct tcache_entry
{
struct tcache_entry *next;
} tcache_entry;

可以看到里面就是指向下一个空间的指针

1
2
3
4
5
6
7
8
9
10
/* There is one of these for each thread, which contains the
per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each
time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
char counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;

tcache_perthread_struct里面是两个数组个数是TCACHE_MAX_BINS(默认是64,也就是说和smallbin的范围差不多),count是各个大小tcache的实时数量(它用的是char,毕竟数不大,省空间)。
entries数组里就是各个大小Tcache的头部指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* Caller must ensure that we know tc_idx is valid and there's room
for more chunks. */
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
assert (tc_idx < TCACHE_MAX_BINS);
e->next = tcache->entries[tc_idx];
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
}

/* Caller must ensure that we know tc_idx is valid and there's
available chunks to remove. */
static __always_inline void *
tcache_get (size_t tc_idx)
{
tcache_entry *e = tcache->entries[tc_idx];
assert (tc_idx < TCACHE_MAX_BINS);
assert (tcache->entries[tc_idx] > 0);
tcache->entries[tc_idx] = e->next;
--(tcache->counts[tc_idx]);
return (void *) e;
}

可以看到,put(free)还是get(malloc)操作,无论是对比smallbin还是fastbin都是可以忽略不计的检查(对范围和大小进行了简单检查),
没有对齐检查,
没有inuse检查,
没有size检查,
没有链表指针检查,
基本上是你往指针域写哪儿,下一步它就跳哪儿。
Tcache是FIFO,每个Tcache最多可以放7个

简单说一下它的运行逻辑
它就像一个空间更大,更优先的容器空间(像fastbin),在一定范围里的内存都会放进去,也会优先从里面取。

  • 每一次malloc(0x400以下),先查看对应的Tcache里是否有chunk,有就返回(在libc_malloc里)。

  • 如果没有,就接着进入int_malloc,会按顺寻依次查看fastbin和smallbin中的chunk

    • 此时,如果有符合条件的chunk且Tcache没满,就把第一个返回,其余的塞到Tcache,直到Tcache满。
  • 如果遍历过程中,Tcache满了,就直接从bin中返回一个chunk(符合条件)

  • 如果还没有,执行unsorted bin大循环(在这之前还是会执行consolidate,将fastbin合并并放进unsorted bin),遍历和操作每一个,直到遍历结束或者达到上限(1000)

    • 如果遇到比我们request大的chunk,切割并返回,剩下的还是unsorted bin
    • 如果遇到和我们request一样大的chunk
      • 如果Tcache已满,直接返回
      • 如果Tcache没满,继续循环
        • 如果最后Tcahe满,直接返回
        • 如果Tcahe没满,最后从Tcache返回
    • 如果遇到比我们request小的额chunk,将其放入相应bin,并继续循环。
Read More
post @ 2022-03-12

Fastbin double free

House Of Spirit

简介

House of Spirit 是 the Malloc Maleficarum 中的一种技术。该技术的核心是在目标处伪造fastbin chunk,将其释放,从而分配至指定地址的内存

要想构造fastbin fake chunk 并将其释放,可以将其放入到对应的fastbin链表中,需要绕过一些必要的检测,即

  • fake chunk的ISMMAP为不能为1,因为free是,如果是mmap的chunk,会单独处理。
  • fake chunk 地址需要对齐,MALLOC_ALIGN_MASK
  • fake chunk 的size大小需要满足对应的fastbin的需求,也需要对齐。
  • fake chunk 的next chunk 的大小不能小于2*SIZE_SZ,同时也不能大于av->system_mem
  • fake chunk对应的fastbin链表头部不因该是fake chunk,即不能构成double free

有个演示(但我没看,看不懂)

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
#include <stdio.h>
#include <stdlib.h>

int main()
{
fprintf(stderr, "This file demonstrates the house of spirit attack.\n");

fprintf(stderr, "Calling malloc() once so that it sets up its memory.\n");
malloc(1);

fprintf(stderr, "We will now overwrite a pointer to point to a fake 'fastbin' region.\n");
unsigned long long *a;
// This has nothing to do with fastbinsY (do not be fooled by the 10) - fake_chunks is just a piece of memory to fulfil allocations (pointed to from fastbinsY)
unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));

fprintf(stderr, "This region (memory of length: %lu) contains two chunks. The first starts at %p and the second at %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[7]);

fprintf(stderr, "This chunk.size of this region has to be 16 more than the region (to accomodate the chunk data) while still falling into the fastbin category (<= 128 on x64). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n");
fprintf(stderr, "... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end. \n");
fake_chunks[1] = 0x40; // this is the size

fprintf(stderr, "The chunk.size of the *next* fake region has to be sane. That is > 2*SIZE_SZ (> 16 on x64) && < av->system_mem (< 128kb by default for the main arena) to pass the nextsize integrity checks. No need for fastbin size.\n");
// fake_chunks[9] because 0x40 / sizeof(unsigned long long) = 8
fake_chunks[9] = 0x1234; // nextsize

fprintf(stderr, "Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[1]);
fprintf(stderr, "... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");
a = &fake_chunks[2];

fprintf(stderr, "Freeing the overwritten pointer.\n");
free(a);

fprintf(stderr, "Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[1], &fake_chunks[2]);
fprintf(stderr, "malloc(0x30): %p\n", malloc(0x30));
}

例题:

lctf2016_pwn200

Read More

UAF

post @ 2022-03-12


前言

前段时间想了想,还是说把自己之前学的一些东西整理整理,哪怕可能没什么值得关注的点,但也算是我自己的一个总结吧,把我踩过的一些坑,记录下来,也希望帮助后来的同学一点,哪怕是一点点呢!

这段时间,就写呗。

原理

简单来说即使Use After Free的字面所表达意思,当一块内存被释放之后再次被使用。

一般是出现在动态内存,使用了malloc等一系列函数以后,相应的指针没有被及时置0(NULL),当我们再次使用时,就有可能会造成内存(地址)泄漏。

不要小看,内存泄漏的危害,可以很大,轻则程序崩溃,重可以通过一系列巧妙地利用,使用特定构造exp获取系统的shell

Read More
post @ 2022-03-08

前因

之前大一的时候,什么都不会,老是觉得这难,那也难。从最开始的C语言开始学。不说关于底层的东西了,就是内存这个概念都没有理解到。什么虚拟内存,映射,操作系统,内核。mmd,头皮发麻。一点一点总结,一点一点学习吧,之前是看了很多书,很多文章,但是一直都没有记录下来。这一段时间其实是一直在补之前的的一些东西。刚看到wiki上有关于elf文件格式的一些更新,想想,我也记一下吧,以下记录以wiki上摘录的为主,同时以俞甲子前辈等人的《程序员的自我修养》的内容,以及其它资料为补充,实时更新。

–====——————————————-===—

正文

简介

ELF(Executable and Linktable Format)文件,也就是在Linux中的文件目标,主要有以下三种类型

  • 可重定位文件(Relocatable File),包含由编译器生成的代码以及数据。链接器会将它与其他目标文件连接起来,从而创建一个可执行文件或者共享目标文件。在Linux系统中,这种文件的后缀名一般为.o。这一般是中间文件,一般还不可以直接在操作系统上运行。

  • 可执行文件(Executable File),就是我们通常在Linux中执行的程序(通常是没有后缀名的)。

  • 共享目标文件(Shared Object File),包括代码和数据,这种文件是我们所称的库文件,一般以.so结尾,一般情况,它有以下两种使用情景:

    • 链接器(Link eDitor,ld)可能会处理它和其它可重定位文件以及共享文件目标,生成另外一个目标文件。
    • 动态连接器(Dynamic Linker)将它与可执行文件以及其它共享目标组合在一起生成镜像

关于 Link eDitor 的命名,https://en.wikipedia.org/wiki/GNU_linker

em….看一下,知道就行。。。

目标文件由汇编器和连接器串讲,是文本程序的二进制形式,可以直接在处理器上运行。那些需要虚拟机才能执行的程序(java)不属于这一范围。

Read More
post @ 2022-02-28

====

还是补之前没做好的笔记,真就好记性不如烂笔头了,哈哈

还是说老年痴呆提前了

还是老规矩,先看wiki

当初理解unlink,因为方向错了。很是废了一大波劲(可能还是太菜了吧0.o……)

WIKI上的解释
https://wiki.x10sec.org/pwn/linux/glibc-heap/unlink-zh/
unlink_smallbin_intro.png

检查:

1
2
3
// fd bk
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
malloc_printerr (check_action, "corrupted double-linked list", P, AV); \

其实本质就是在P上伪造fd,bk
利用UNLINK机制(注意:这是一个动作):

1
2
3
4
FD=P->fd
BK=P->bk
FD->bk=BK
BK->fd=FD
Read More
⬆︎TOP