00:00
今天呢,我们来讲这个一个新的技术啊,这个技术呢,我们来写一下。这个是什么呢?是动态啊,动态获取系统API函数地址,并且调用嗯,这样的一个技术,然后这个技术呢,我们可以大概用在三个方面上,第一个呢是免杀啊,第二个呢是这个壳。第三个呢,是这个code的啊,比较常见的是这三种,当然其他领域呢,也有经常会用到这种的,比如说注入进去之后,呃,你想做点什么隐蔽的事情啊,也可以用这种方式。那么我们这三个方向呢,用的比较多啊,都是因为什么呢?首先呢,我们来说免杀,免杀之所以用这个东西呢,是因为有一些这个。
01:11
有一些啊,这个敏感的啊,敏感的API或者敏感的API组合会被什么,会被这个杀毒啊,杀软或主房监控。啊,那这种情况下呢,如果说你这个有这种这个很明显的导入的情况下啊,那可能就是呃,会这个对你的监视更严,或者直接杀掉啊,什么是导入啊,就是我们这个PE结构中的这个PE结构啊,导入表的监控啊,比如说我比如说啊,我这个导入表啊,我现在呢,给大家演示一下,我这儿有一个呃load PE啊先把它打开,打开之后我选择一下我桌面上的一个这个程序啊,我们先把它的这个目录表打开,然后打开它导入表,导入表你可以看到它有这么多导入表啊,这个里边呢,就能说明很多很多的这个关系,比如说我们这里边。
02:09
有什么这个3132啊,有什么这个呃,U332G di32啊,里边有某些这个API啊,它大致上可以说明你这里边可能会具有什么样的功能啊,不一定一定会有,但是可能会有,你知道吧,那如果说我们处理之后呢,那么它大致会只留下一个克诺三二,因为克诺三二这个东西呢,是你的进程啊,它会用到的啊,所以说呢,基本上每一个都有能三二,如果连科三二都没有的话,那比较奇怪啊啊,这Windows进程啊,如果没有科三二也很奇怪啊,那所以说呢,我们可以把它只留下一个克能三二这么一个情况啊。啊,那这种是第一种情况啊,就是如果导入这个杀软啊,对你导入表有一个监控的情况下,你可以通过这种方式把它绕过去啊,当然这种方式现在比较弱鸡啊,很难做到杀啊,你要组合其他的一些方法才行,那第二种是什么呢?就是壳啊,你这个壳呢,是要这个附加到别人的这个程序上的,那么这个时候你程序有些导入这个。
03:06
啊,动能模块啊就很难说啊,那么这种情况下,如果你要调用一些API,那最好的方式就是什么呢?就是我自己加载进来,然后呢,我自己去这个用啊,啊就是这因为这个啊避免目标程序没有自己所需的DL动态链接库啊这个这个目的第三个就是cell code cell code的目的呢是不依赖于啊环境。就可以运行,所以啊所有的啊所有的API不能依赖于啊环境。自身具备啊,不能依赖于自身具备,那就得自己找了,对不对啊,那所以说你要写一个通用的啊,在什么地方都能找到这个API的方式啊,那我们这种这种技术呢,大致呢,会用在这三个方面啊好,那我们现在呢,来聊一下东西啊,就是我们要做到这一点,那应该怎么做呢?其实呢,也非常简单啊,它里边两个灵魂函数是什么呢?一个是这个load library。
04:16
一个是load library,还有一个呢,就是这个get PC address啊,就这两个函数啊,比较关键,因为有这两个函数,你几乎可以获取到所有的这个API的一个地址啊,然后来进行一个调用啊,那比如说我如果要调用load library,那起码你要先找到load library这个东西呢,你要干嘛呢?你要这个依赖于哪个呀,依赖get来获,为什么要这么说呢?因为首先啊,我们啊有了这个这个函数才能干嘛,才能加载其他的函数啊,然后呢,我们有了这个数就可以把的这个。这个函数加载进来,然后他们俩组合起来,就可以加载任意块的任意函,那我们要找到他们俩先怎么做呢?首先我们要找到这个library和这个get。
05:12
便利谁的导入表呢?便利科三二。克NO32的导入导入表啊,然后呢,就可以找到啊这个get bic address的这一个函数啊,那我们要要把要便利它的情况下,你首先要有这个克EL32,所以说呢,你要干嘛,第一步呢,是在这个系统中找到啊K32K32.dl的base啊,找到这个base之后,你才能通过它啊,然后来导来遍利这个模块,然后呢去找它的这个地址,而找到这个地址之后呢,刚好我们的这个呃load library啊,它也是这个我们科NO32里导出的,所以说呢,你可以通过它直接把这个科NO32的这个base啊,然后呢,给它放入到我们的这个位置上,三二的base啊放在这,然后呢,第二个呢,就是你要找的一个名字啊一个,那么有了这两这两个函数之后,这个时候他们俩就都有了嘛,有了这两个函数之后,无论你以后要找什么函数,比如说你要找这个US里边的这个。
06:19
叉叉叉三二函数,那么这种情况下你就可以直接啊干嘛呢?首先通过这个呃load library啊,把这个你的这个三二叉叉叉UU332这个啊给它加载进来啊,加载进来之后获取模块聚柄啊,在这获取它的一个模块聚柄,获取完模块聚柄之后呢,再用getpc和address啊来这个给它获取到我们的这个函数的一个地址啊去经过这么两手,这个呢,就是大致上它的一个原理啊,啊无论你是用免纱还是壳,还是扣的,基本都是这个原理,但是它们之中呢,有一些细节上的不同啊,比如说我们如果是三这个三扣的,这里边扣的里边呢,它是尽量不要使用我们的这个字符串的啊,因为这个区域不同,你可能找不到这个字符串啊,那壳里边呢,就没什么特别明显的要避免的东西啊,那免杀这里边儿呢,可能会有一些其他的东西需要注意啊,那所以说呢,它有一些小细节是不同的,我们这个时候呢,就先写一个这个适用于什么呢?适用于这个大。
07:19
大部分情况的啊,当然不是啊,这两个啊,都可以用这种模式来进行获取的这种这种代码啊,那我们现在呢,先打开我们的window studio。新建一个这个新建一个空项目啊。这个东西算什么啊,算是这个。也不知道叫什么,随便吧,就就就就就这个PROJECT24得了啊,你点击确定。好,然后呢,我们把这个解决方案这点出来,然后呢,新建一个原文件,点击新建项,然后在这个新建项里啊,创建一个may.cpt,接着呢,我们在这个上面呢,右键啊给它点一下属性,在C加加上面代码生成啊,设置MTD,然后呢把这个环节库关掉,用用确定啊,然后呢,现在呢,我们先包含一下这个头文件和最基本的这个框架啊,我们只需要包含一个windows.h就可以了,这个东西呢,主要是为了给我们一些类型啊,类型和投和这个结构体啊做一个定义啊,其他的东西我们都不使用啊,不,不使用它对API的一些定义啊,我们都那些东西都自己找in特妹,然后瑞特零,好,那现在呢我们就开始写啊,那首先呢,我们要获取到我们的这个呃,CEL32啊,这个地址啊,那我们这个CEL32地址呢,在32位下肯定是一个ord对吧,那我们现在呢,就用一个ord来对他接收啊,一个get。
08:52
COLONEL32ADDRESS啊,这样的一个函数什么也不需要传入啊,那首先呢,我们定义一个函数用来返回啊DW啊。
09:08
32A drr等于零啊,我这一节课呢,使用的是这个汇编的形式啊,如果说你写的是一个64位程序,我建议你使用指针的形式来进行这个查询啊,他们俩的效果呢是一样的啊,因为能用汇编写的,你用指针几乎都可以写出来啊,很少有写出来的啊,当然有一些特殊情况也确实写不出来啊,那我们push ES,首先把它ES值给它保存起来,在临走之前呢,得把ES给它pop出来,在中间呢,首先呢,我们要找一下这个PB的一个地址,那PB它这个东西呢,是在这个FX30的这个位置上,FX30这个地地址上,首先呢我们把它拿出来啊exx,然后呢是这个or PPR啊FS300 S30啊,注意是16进制三零啊,在这个位置上是我们的这个PB,那我们peb呢,我们现在呢,先来把它这个调试器啊给它断下来,我们来看一下。
10:05
嗯,啊,然后首先我们d TD t peb,好,这是peb的一个结构啊,我们现在呢,观察一下PB的结构,你可以看到它在这个呃,0C的这个位置上有一个LDRR,它这个LDRR呢叫什么呢?叫做啊PBRD塔啊这么一个结构啊,那我们现在呢,要找的就是它,所以说呢,我们现在呢,通过这个木啊EXAX目EXAX,然后呢,是我们用啊这个PB啊,现在我们ex里存的是PB的手提纸嘛,那我们用ex加上啊,Ex加上0X0C啊现在呢,我们已经找到这个0C这个结构了啊,那我们现在呢,来看一下0C这个结构里边存的是什么东西,再次DTDT这个结构啊,这个结构,诶啊,它好像没有这个结构啊,我们这个符号不不全好像。
11:02
啊也不是,好像我多打了一个下划线啊,这回有了啊,然后呢,你可以看到啊,这里边就是我们这次要找的东西啊,我们这里边要找的是什么呢?是这个东西看见了吗?它这个东西呢,是一个什么呀,一个初始化的一个模块列表啊,就是你这个呃,它是一个list entry啊,这个list entry这个结构呢,实际上而言,它只有两个成员啊,你可以看一下,一个f link,一个b link,那我现在呢,要找的呢,实际上是在它ec位置这个东西,那我现在呢,就首先啊给它目出来木ex,然后是E,因因为我现在这个exs呢,是指向这个我们这个呃PB DR data塔这个地方的,所以说呢,现在呢,我们要通过这个l DR data找到它加ec这个偏移这个位置的东西,所以用0S这个ES加上0SEC,然后呢,拿到它的初始化这个链表,拿到初始化链表之后呢,我们这个里边呢,可以看到它是什么呢?它是一个这个list entry list entry里两个成员,一个是f link,一个是bli,那现在呢,我们是要。
12:01
找到这个blink指向的这个成员,这个里边呢,实际上是指向了一个叫做什么叫做什么来着,叫做我想想啊,呃,不太记得了啊,就是叫什么LD data table,应该是这么一个结构啊,然后呢,我们现在呢,来找到他。木ex,然后ex直接取出,那这个结构里呢,我们首先呢,我们有两个这个它这个地地方实际上就是存储的就是drl base了,然后呢,我们这个dl base呢,是有顺序的啊啊,但是这个顺序呢,无论是你什么样的操作系统啊,从这个WIN7啊叉P啊之后啊,应该都是一样的,是什么呢?首先0X4的位置上是NT dr.DR2 0X8的位置上,要么是C32.dr,要么是C32B呢C点这个DR啊反正这两个功能差不多,那首先呢,我们现在呢,要找的就是科三二啊,那所以说呢,我们要给它这个获取这个exx啊,然后exx加上0X8啊,零八这个位置的一个这个数据啊,把我们CR32的一个base出来,拿出来之后呢,现在我们C32的base就已经在ex里了,然后呢,我们上边不是有一个变量嘛,然后把它到我们这个变量里。
13:10
目录到变量之后呢,我们pop ES啊进行还原,还原之后我们直接return啊,把这个变量return出去,这样呢,我们在调用这个函数的时候呢,就可以获取到我们的这个克能三二了,好,然后呢,我们获取完克能三二之后呢,接下来呢,我们再来拿一个什么呢?拿一个我们的这个PLC address的一个地址啊,那我们现在呢,再来啊,Get pcss啊,这个函数的一个地址,那我也不能这个跟系统API重名了,我们我也不能写一个get get呀,对不对啊,那我就随便写一个,嗯。R啊,我加一个R,好,然后现在呢,我们开始获取啊,那首先呢,我们要做的事情呢,就是把这个坑base啊获取出来啊,Ord啊,然后ad啊,Base等于啊我们一获取,然后呢这呢,我们就拿到了这个克能三二的一个base,拿到克三二的base之后呢,我们接下来呢,要解析它的导导出表啊,因为我们这是一个系统的动态间接库,我们要来这个获取它的这个导出表,从它导出表里拿到我们get PLC address的一个地址,所以说呢,我们现在呢,用一个这个P啊,Image啊,Image do hander啊,来里边找到它的这个稻子头。
14:30
然后一个PDOSPDOS等于它,然后直接从这个啊,把它作为一个什么起始地址,对吧,因为我们这是这个的,第二接下来呢,我们要找它的NT头啊,就是p images ntt nt等于啊这个呢,是通过我们的稻子头找到的,用我们的这个稻子头里的这个e fanw啊,然后加上我们的这个base斯就达到了我们的NT头,拿到我们NT头之后呢,接下来呢,我们要获的是这个数据表,就是p image。
15:15
然后这是目录表。等于啊,它呢是通过NT头来寻找的,也就是这个NT头里边有一个option option啊这个实际上就是扩展头啊,在扩展里头有一个这个数据目录表,然后用这个数据目录表啊,再加上我们的这个导,呃,导出表的一个偏移啊。我们通过这种方式直接定位到这个导出表的一个这个呃位置啊。DRE。导出啊,这个导出好,那现在呢,我们就拿到了它导出表啊,导出表这里边呢,它存储的是什么东西啊,这个数据目表里,它一共是存储了两个结构,一个是rise,一个size,也就是我们导出表的这个虚拟地址啊,还有什么,还有它的这个size,那现在呢,我们来获取这两个东西之后,我们就可以找到它真正的这个导出表在哪存着了,也就是我们这个文件里它具体在哪了,那我们用一个导出表的一个结构。
16:32
好,这是导出表的结构啊,Ex p rt等于强转一下啊,等于什么?等于我刚才的这个de base啊,用这个我加个括号吧,等着它有歧义de base啊,加上我们这个,呃,目录表定位到目录表啊,这个导出表它里边这个微address啊,也就va,然后呢,给他这个获取一下它的这个呃,地址啊,它其实不是va,应该是rva啊好,那么接下来呢,我们要找啊,导出表已经找到了,那么现在呢,我们要分析它里边的这个内容了啊,我们这里边呢,其实一共有三个比较重要的东西,一个是地址表,一个是名称地址表,一个是序号表啊,那一会我们挨个给它获取一下,在这之前呢,我们先给它,呃搞两个东西出来,DW啊DW啊,Fun content,就是一个函数的一个总数啊,这个呢,直接通过这个导出表,它里边有一个这个number of。
17:32
啊,这个东西啊给拿到,这是导出表的一个这个这是函数总数量,然后呢,我们需要一个这个函数名称的一个总数量。Sun name content等于这个。那啊这个好,接下来呢,我们就要给它把三个东西都声明出来,三个表啊,一个是函数地址表,一个函数名称地址表,一个函数序号表,这三个东西啊,然后没点关注点关注啊,咱们每周六周日晚上都要直播啊,然后呢,我们这个。
18:08
呃,如果需要领取课程之类的,可以直接联系咱们老板啊,然后我继续啊,那个我这个呢,首先是一个函数总数,不是函数总数里了这个函数,这个函数地址我们用一个啊不对,那应该是这个应该用一个pd word。P啊。我想想。嗯,对啊,PA DR of fun等于。Pdor啊,然后圈上用刚才不是这个东西吗?这个函数的一个总数啊,函数地址的一个总数啊,那不对,不用这个是这个点a DR of这个这个就是函数地址表加上什么,加上我们的base啊,就是它实际上在文件里的一个偏这个位置了,然后我们直接把这个表给取出来了,取出来之后呢,第二个也是类似的套路啊,这个函数名称地址表。
19:10
PA DR of names。等于。Pd word,然后上边是导出表,哎呀,复制多了。点ADD啊,Names加上DWa.base啊,从这个模块文件的起始位置开始找好,那么我们找到之后呢,我们还有第三个就是序号表啊,序号表跟前面两个不一样啊,它不是por啊,是p word,这需要注意啊,如果一不注意就容易写错。Keyword。
20:09
序号加上base,好,这样呢,我们就找到了它的这个三个表啊,找到三个表之后呢,我们现在呢,再来定义一个变量啊DWD这个呢,是函数地址啊,一会儿我们要找到我们想要的函数之后啊,用它来做一个这个操作。诶,不对,我们似乎不需要这个东西,那算了,删掉吧,啊,我们不需要这个函数啊,那我们接下来呢,开始给它这个进行一个复数循环啊,复数循环然后呢,负数循环的总数呢,就是函数的一个总数啊丢在这里,接下来呢,我们就判断判断一下什么呢?判断一下我们的这个函数地址表是不是为空。啊,当前这个函数地值表啊,这个这一项,因为我们已经拿到这表了嘛,那么接下来呢,我们就在这个利他这个数组啊,如果这一项是这个没有的情况下啊。
21:02
那么这种情况下,我们就直接给他continue跳出好,如果是有的情况下啊,那接下来呢,我们就来这个拿到它的一个函数地址的一个,呃。呃,应该算是偏移吧,我们一个or。DW fun drro set等于PADR第二个。好,拿到它的这个之后呢,我们接下来呢,要开始这个循环,便历第二步啊,第二步呢,它的总数呢,是按照名称的总数来算的,因为我们实际上而言,要便利的函数都是有名字的表,因为它有一些函数呢,导出之后没有名字那种也不是我们关心的,因为我们这要找的这个东西肯定是一个有名字的是什么呢?就是get p r和address,那么明显的一个名字肯定是有啊。
22:00
然后呢,我们现在呢,先来对比判断一下这个序号表和我们的I是不是相一致啊,因为我们这些东西呢,都是从这个零开始的,那首先呢,我们这不是有一个序号表嘛,然后我就从这个序号表嗯,找一下,找一下什么呢?我这个第二层的I呢,我给它换一个,比如说我换个C。我的C啊,是不是等于等于I,如果是的情况下,我们就进入啊,进入我们的对比模式啊,就是把每一个有名字的函数的对比一下,首先呢,我们获取一下它名称的一个偏移啊,因为我们现在呢,实际上它是一个这个偏移啊,我们还要获取到它文件中的地址,具体这个如果不懂的情况下,咱们前面有一个Windows PE的一个公开课,你可去看一下那个啊,那里边讲的比较详细,然后呢一个。DW name of等于PA DR of names的C,好,然后呢,我们有了这个之后呢,我们就可以在文件里的相应位置上把这个函数的名字啊给它取出来,等于叉C。
23:20
嗯,Dad wa base,然后加上U,呃,DW name of that。我想想啊。应该是这样啊,然后再下一步啊,我们就进行对比判断一下。STRCMP啊,判断我的这个名字和get PC DR ress是不是相同,如果相同呢,就判断是不是等于零啊,如果等于零的情况下啊,那么我们接下来啊,就可以返回了,返回什么呢?返回首先呢,我们现在已经拿到它这个地址了,对吧?那么就是我们的这个DW fun DR,但是呢,这个东西只是一个偏啊,你要拿的呢,是它实际上的一个地址,也就是说它真实的这个地址在什么位址上,那这个位置在哪呢?就是用这个偏移加上模块的手地址,然后就可以拿到它在模块里的地址了,好,那么现在呢,就可以获取到get PLC address了,好获取完怪C呃get PLC address之后呢,接下来呢,就是你要你要用什么函数,你要给它明出啊它的这个函数指针,那我们现在呢,都需要用什么东西呢?首先呢,我们要这个肯定是load library和get PC address。
24:48
是要有的,然后呢,比如说我们现在呢,要演示一下,比如说我们弹出个消息框之类的啊,那就用一个消息框的函数,那首先呢是这个load。我们找一个low library a啊,你千万别去找红啊,它模块里是没有红的啊,它这里边儿是要么是A要么是W啊。
25:08
STERN。Cap。Type。啊,这是啊,然后呢。OK,一个啊,简单整理一下,给它放到一条线上,然后把它改成函数指针的样子。把这两个给它圈起来。然后中间加个星,再给它改个名FN,好,这样呢就是函数针了啊,有这个函数针之后呢,接下来我们下一个啊,下一个比如说我们找这个get p ROC address。
26:04
F12。回来啊,然后前面是一样的啊,直接复制一份拿过来,然后把它拿过来。好,然后圈上。好,接下来呢,比如说我们要弹个窗啊A。
27:08
诶。好之后来一个退出。好,声明都声明好了,那接下来呢,就是开始找他们的地址了,首先呢,第一步呢,肯定还是要去找这个get p address这一个地址啊,那我们就来。把它指针拿到这儿,然后呢,我们这是一个PFN啊,Get PL address啊,直接加一个P就完事了,P啊。
28:08
等于旋转,旋转完事之后r get。Prol address啊,来获取,获取完事之后,我们现在找到PL address了,那接下来呢,我们拿到这个这个首先我就拿到一个base,然后呢,我们才能去获取这个load library,因为它的第一个这个模块句柄需要这么填,所以说呢,我们现在呢,要来获取一下啊,那就是一个word啊DW啊克三。等于啊,或者这呢,直接用那什么也行啊h more啊用用这个也行啊啊然后呢,拿到它啊就是GETNO32。Address获取啊,它类型不符,我们给他强转一下啊,这样就没问题了,获取完事之后呢,接下来我们就可以获取这个load library了啊这事啊,这个load library load library啊等于。
29:15
PF load library等于get p9address直接调用它,调用它呢,首先呢,它这个类型肯定是不符的,在前边呢,对它呢进行类型强转换,然后它的第一个参数啊是这个呃,模块句柄啊,直接填上去,第二个呢是名字啊,那名字呢,我们这儿不是load library a嘛,那我就直接给它填进去就行了,好找到这个library之后呢,剩下的就好办了啊,那比如说我现在呢,要来找两个模块啊,这个H模的呃。这个改H吧,H好看一点,也比较符合要求啊,然后H,比如说三二等于。我们library呢,啊,这library。
30:04
The library啊,然后是什么名字,USER32点点,好,然后呢,是我们的这个科NO2啊,这都是常用的,但是科NO2其实可以用另一种方式啊,Get model handle也一样啊,因为这个东西几乎是必然加载的。哎,不对,我上面有科塞尔。我想想啊啊对,我这获取克诺三二了,我还获取它干嘛二了,好,我们已经有克诺三二了啊,然后呢,继续呢,我们就开始找他的这个ma box image box,等于啊,然后get p address来给给他返回类型强制转换,然后呢。后边。它的模块呢是U332。
31:00
然后名字。好找到了,找到之后呢,接下来我们去找这个退出。这个退出呢,他在克NO32里。好都找到之后呢,我们现在呢,就可以调用这个API了啊,来弹出一个消息框。好,然后我们退出。我们重新生成给他测试一下啊,没点关注的点点呃,有回音是吗?啊,没点关注的点点关注啊,然后呢,每周六周日都有直播,有需要课程代码工具的啊,可以联系咱们的老板直接领取啊。
32:11
好运行。嗯,有一个错误啊。我看一下。在这儿对比的时候出问题了。白。
33:02
嗯,我从这下个断点看一下吧。走地址获取到了啊,应该没问题。到头也有。NT头也没问题。那这块应该是都没有问题的,总数啊,771。哦,我操这个怎么这么多。哎,这地址好像不太对,我看。啊,这块错了啊,这个名总数我写成这个address of names了,它应该是number of那个names啊,所以它会问题啊,然后新再。哎,你看它这就正常弹出了啊,我们这个东西呢,也没有依赖什么其他的一些东西啊,比如说我们刚才调用了Mac bos,如果正常情况下呢,它的这个ESE里应该是有这个导入这个右侧三二的,但是现在呢,我们可以通过这个load这个load PE啊来看一下。
34:17
目录表啊,导入表,你可以看到它只有科诺三二啊,其他什么都没有啊,你包括你以后如果用一些敏感的API啊,其他的一些API啊,它都是不会有的啊,因为什么?因为我们是通过动态的方式啊来获取到的,包括我们的啊三二啊艾PR address啊呀什么的都是动态获取到的,本质上而言,除了系统它必须要调用的科诺萨里的一些函数之外,我们其实什么都没有用啊,所以说呢啊,就可以达到这样的一个效果啊,有没有什么问题啊,如果没有什么问题的话呢,我们这个技术部分啊就讲完了。有需要领取这些代码啊,工具啊之类的,可以联系咱们老马啊。
我来说两句