00:00
大家好,这个今天我们来看。Return to CU,然后再看return to csu之前我们来首先需要看一下叉八六和叉六四它在传参上面的一些区别,对于叉八六来说,也就是我们之前说过的那些例子,它都是把参数放在这上面的,然后但是对于叉六四来说,它前六个参数会依次保存在这上面,那如果还有更多参数的话,它才会保存在站上,嗯,这是他传在的区别。然后下面讲的三个例子,包括return tosu,都是蒸米LP叉六式的那篇文章里面的例子,然后因为VK里面讲return to csu也是用的蒸米的那个例子嘛,所以就就按照蒸米那个直接讲了。我们来看第一个例子,这是它给出的源码,可以看到它是有一个system这样的一个函数的,那我们可以直接利用返回到那个地方吗?嗯,但是如果你。
01:07
GDB,你去让他。用以前的方法去找他的返回地址,占空间有多大的话,会看到是。有些问题的,他报的这个东西并不是这里面的某一段字符串,而是这个地方对吧?那这个原因是在程序使用的内存地址如果大于它的话,它会抛出一个异常啊,你就说它不会去执行那个东西,但是我们还是可以通过查看它的RP寄存器去看一下它此时RP里面存的是什么,因为返回的话就是返回到RP上的。
02:00
那个地址嘛,然后但是这里如果你直接拿前面这四个来算的话,还是不对的,因为它里面存储的是小端序,也就是说它存的顺序是正好相反的。那你也可以看到这里是JA,但是如果你想要去找JAAB的话,你应该是这样才会才是正确的。零差,这样是136,但是如果你去找前面的。它显示的140,也就是说它多了这四个字字节。那这是一点问题。那我们已经知道占空间了,然后它里面也有一个system函数,所以我们直接去找到那个system函数的地址,然后让它返回过去,就可以执行我们的达到我们的shell了,啊,我们在ID,在IDA里面。
03:24
看一下他这个。Co system函数的地址,按一下空格就可以看到它那个地址了,然后是这一个。那我们运行一下这个一叉P。可以看到是成功了,难道是了,但是这一个来说,它并没有涉及到传餐的问题,我们来看下一个。嗯,就是下一个例子的源码,它会调用这个函数,这个函数会把system这个函数的地址给打印出来,我们运行一下看一下。
04:13
可以看到它把system函数的地址又告诉我们了,然后那这样的话,我们就已经知道这个函数的地址了,我们只需要把杠B-SH的参数给他就可以了。那但是如果你想要给它参数的话,需要把它放在RT里面,而不是站上,也就是说我们需要从站上把它给弹到rdi里面,需要用pop质量,那那这样的话可以用lp and get来找一下刚刚bary指定的是他的那个文件,然后刚刚奥利找什么对吧。
05:10
我们要找的是泡泡,然后return,再筛选一下带带有adi的。那他帮我们找到了在这个六四这个程序里面存在的这样的一个god get,但是在真米的文章里面,他说的时候是在程序里面没有找到,然后在LA里面找啊,可以用LDD这个命令看一下他用的是哪个LA。这样的话就可以看到了,然后再把这个刚刚班的参数换成这一块就可以了。嗯,这样的话它是有区别的,那我们找到的是直接在程序里面,我们直接用就可以,但如果是在这个LA里面找到的话,它实际上是一个偏移的地址,而不是那种就是真实地址吗?那需要根据LA search,它不是给我们system函数了吗?
06:13
找到LA的版本,然后把LA的基值算出来,再把这个东西加上LA的基值,才是它真实的地址,你是说如果按照这种方法去找的话,一叉P应该是这样的,那我们就直接。直接用这个地址就行了啊。嗯,然后这上面是接收,就是说因为我们运行嘛,它这里有个换行,然后在换行之前的就是他的地址了,那他的话就把换行之前的。作为system的地址,然后把它转化成那种整形的,再根据LA4去搜就可以了。
07:00
那这个pop的话,因为返回到pop pop r Di,然后return嘛,那它会把这一个。杠B-SH的那个地址。也不是啊,就是把杠B-SH给pop到rdi里面,然后返回的话就返回到system了,然后它再执行system函数就拿到she了。啊,这是第二个例子。我们再来看第三个例子,那就是return to CU了,那这个的话它属于X64下面一些万能的can get,然后。对于只要是调用了LA的话,它就会用这个函数进行对LASO的初始化啊,然后就是说肯定会有他的,那我们看一下。哎,不对。
08:10
嗯,但是它如果直接用o dump的话,它显示的不是我们熟悉的那种汇编格式啊,可以加一个杠M的参数。然后告诉他把它编译成in特尔格式那种汇编,这样它就显示的是这种比较熟悉的格式了,那我们找到它在这里。你知道这个地方。那我把这一段称为一,然后上面这一段称为二,首先它会调用一把站上的数据挨个的放到这些。
09:01
寄存器里面,然后调用这个第二段把。寄存器从这样从25方到RDX 24方到RSI嘛,就是这种形式的话。你就可以构造我们需要的参数了,然后,然后通过这个扣去调用我们想要让它调用的那个函数。嗯,我们直接看一下配的。首先是引入了两个库,然后这两个的got地址,这里是直接用IDA可以看到的,就不说了啊,我们直接看这个配照的,那第一串配照的当它啊,先先预习一下。他会说一上哈喽吗?那就是说当输接收完这个哈以后。
10:02
再发出去啊。那整个这一串打过去以后,这样的数据这样的,嗯,然后先是136,也就是通过那种方法可以算出来吗。这样的占空间占满以后,这是返回地址,那它返回到这个地址是在这一个,也就是它的第一段gets,那这样的话下面因为它调用它以后占RP就成了这一块了啊,然后。也就是说相当于他已经加了八了。然后如果RSP再加八的话,实际上是这里了,嗯,这里就相当于是填了一个填充数据吧。然后他会把RP加八的数据也是这里的数据放到RBX,然后下面是加16的话放到RBP就是。
11:05
经过这一段以后。实际上他们就依次放到我写的这样这样里面的,嗯,然后在RSP加38H,那38H是呃,56 56。直接原本RSP是在这的,那加上56以后就来到这了,它返回到了是第二段。这样的,然后第二段再去用这三个Mo指令,分别放到RDRSI和RDX,那我们看一下。参数存放顺序,Rdi和RTX,也就是说这三个依次是第一,第二、第三个参数,那这样参数就构造好了,通过我们构造这个东西可以看到第一个参数是一,第二个参数是外的地址,第二,第呃,第三个参数是八那。
12:07
这个函数的原型是一,一是标准输出流啊,就是标准输出,然后第二个参数是地址,也就是说要输出的信息的地址,然后是长度,也就是说我们想通过调用。这下面这个下面这个东西在22里面。因为RBX乘以八,我们RBX的话,可以看到是零啊,然后它乘八以后也是零加上20 22的是这里,也就是这个地right的这个地址啊。也就是我们调用right去把right的地址给打印出来,然后在执行完以后,他回来RBX加上一,RBX原本是是是零的,它加一以后就等于一了嘛,然后下面有一个比较跳转,如果它俩不相等的话就跳,但是我们为了让它返回,返回到这里。
13:04
我们不能让它跳,所以我们之前构造的那个RBX啊,RBP啊,我们构造的RBP就是在这用到一个一的,它两个相等,所以不跳那不跳,然后执行这一堆啊,就像。可以看到它是有个顺序的。如果他不跳的话,他就继续执行下面这一堆了,也就是这一堆啊,那这样的话,因为我们已经执行完了,它怎么再怎么移动也不影响了,无所谓了,然后我再。这一堆末尾执行完以后,有个加38H嘛,那所以我们要在这加多一个50A乘以56来作为填充。那它返回的时候,返回到了就是这个地址,也就是main函数的地址,我们再从头再打第二遍配料啊,第二遍配料的话,填充是这样的。
14:08
它的作用,首先第一个是把write的那个地址给打印出来,然后我们根据这个search去搜它的LA版本啊,然后我们第二第二遍打配的作用是我们我们已经知道它的函数地址了,我们需要把它给写进去,也就是。通过执行这个read。把。杠B-SH写到BSS段,就是把这两个参数写进来之前是没有的,然后我们执行它以后就写进来了,嗯,然后第三个的话就是去执行这一个东西了。他扣的这个地址是system的,然后第一个参数是杠B-SH在这,嗯,就是。
15:02
这样讲一下,自己看图应该会主要讲的要明白点,可以看一下,嗯,需要说的是这个read它是它是个参数,是标从,因为这里有个零嘛,这是标准的输入,也就是应该是从控制台输进去,所以我们这里有个。呃,剩的,嗯,然后它是16个长度。你自己看一下就好了。
我来说两句