脱壳实践笔记-动态空间填充IAT

2022-04-05 0 1,749

01-找OEP:esp定律

  • F8过PUSHFD、esp右键-HW break、F9
  • 单步几下到达:有个sub esp,0x58,下面还有一个call(一般就是GetVersion),故可判定VC 6.0

    脱壳实践笔记-动态空间填充IAT

  • 下面的WinMain也算是Vc6.0的特征<!–more–>

    脱壳实践笔记-动态空间填充IAT

  • 若pushad与pushfd连着,则fd之后再下断
  • 暂停至popfd后,是一个call,enter过去是lea esp
  • call xxx + lea esp [esp+4] = jmp xxx(混淆指令-化简为繁
    • CALL 001E1CD7 = push 001E1CD7+5(sub esp,0x4)、jmp 001E1CD7
    • LEA ESP,DWORD PTR SS:[ESP+0x4]:add esp,4
  • 有些call不是真正的函数,要F7,而非F8

02-填充IAT的地址是动态变化的

  1. FF 15那个call IAT的地方,数据窗跟随,IAT处异常,IAT被壳修改了

    脱壳实践笔记-动态空间填充IAT

  2. IAT处下硬件写入断点,重新运行,检查断下的地方是否正确(有时没有那么准确,一下就到断在理想位置;通过上面的地址和值判断
  3. 第一次断在rep movs那,硬件写入为陷阱类,指向下一条,故rep movs的上一条才是;rep movs 物理上一条为JB语句,也不可能是其他地方jmp过来的,jmp指令不可能触发硬件写入,故舍去

    脱壳实践笔记-动态空间填充IAT

  4. 再一次断在call处,目的地址同1中都是475080,故这就是(源地址不同,但都是xx5039,可能是一个偏移

    脱壳实践笔记-动态空间填充IAT

  5. 在mov 上设置硬件执行断点,去掉原来的硬件写入,重新运行,发现有时会断下,有时断不下;而硬件写入时,每次都会准确断下,推测此指令所在地址是动态变化的
  6. 重复1-5,反复测试,发现mov这条填充IAT的指令地址是不确定的,但是后面那个0895是确定的,应该是一个偏移,所以推测:壳代码填充IAT的代码是在申请的内存中执行 (偏移+申请内存的首地址 = 最终地址
  7. 验证上述猜想
    • 申请内存用 VirtualAlloc,ctrl+g搜索并下断点,堆栈中观察调用处,是主模块调用再停止,否则放行;
    • enter进入调用处,call下1下断,F9使其跑完此函数,返回值eax=300000,这就是申请空间的基地址
    • 基地址+填充IAT指令的偏移0895=0x300895,ctrl+g到内存窗口,发现都是0
    • F9继续执行,发现0x300895此处内存已改变,右键-反汇编,正是mov 那条填充IAT的指令,验证上述猜想

03-准确找到填充IAT的地方

  1. 调用VirtualAlloc的地方0047A37D CALL EAX ,此处下断,运行至此时F8,得到eax即基地址 0x1F0000

    脱壳实践笔记-动态空间填充IAT

  2. 基地址+填充IAT指令的偏移,0x1F0000 + 0x0895 = 0x1F0895,跳到此处,下硬件执行(此时刚申请完内存,具体代码还没有拷过去,所以是一堆00,不打紧,照样下断

    脱壳实践笔记-动态空间填充IAT

  3. F9运行,发现断在0x1F0895(此时就有代码了

    脱壳实践笔记-动态空间填充IAT

  4. 这样就可保证,每次都会断在填充IAT处(不像一开始有时候断成功,有时候失败

04-壳代码中自定义了API

  1. GetProcAddr用来获取API地址,若要填充IAT(别管是不是修改后再填充,都会用到此
  2. ctrl+g,搜索,下断,堆栈中,非主模块的调用放行,测试发现,主模块并没有调用此API(一直放行,都放到填充IAT指令那了都没出现),推测:壳代码中自己实现了一个GetProcAddress
  3. 同样的思路,GetModuleHandleA和W下断,也没找到(真实OEP之后的调用肯定不是,在到达真实OEP前,已经填充完IAT了,也就已经调用完GetModuleHandleA了

05-找获取API地址的地方

  1. 每次运行,都要获取壳代码申请的内存空间的首地址,此时为1f0000(有随机性,每次申请的都不一样,故如此(系统有伪随机性,何况是在虚拟中,尽管如此,也要获取,确保万无一失

    脱壳实践笔记-动态空间填充IAT

  2. 填充IAT的位置偏移0895+基地址1f0000=1f0895,下硬件执行,运行到此

    脱壳实践笔记-动态空间填充IAT

    脱壳实践笔记-动态空间填充IAT

  3. F7单步向下执行,发现进入循环,暂不看代码窗口,只关注堆栈窗口,发现是挨个字符的判断(一个函数名中全部字符的循环
  4. 运行到向上跳的jmp时,就是循环语句,在本jmp指令与它跳往的地方,二者之间,找JXX条件跳转语句,JXX一般就是跳出循环的

    脱壳实践笔记-动态空间填充IAT

  5. 在跳出的xx1ccc下断,F9测试一下,发现就不是一个函数名中各个字符的循环了,而是一个个函数名的循环,表示确实是跳出了内层的循环
  6. 在4的基础上继续F7单步,继续找负责本层循环的jxx条件跳转语句(这一个逻辑正好与4相反,4:跳则出循环,5:不跳才是出循环,但实质相同

    脱壳实践笔记-动态空间填充IAT

  7. 4的循环时一个函数名字符串中各个字符的循环,5的循环是多个函数名的循环,猜测,接下来就是多个dll的循环了(函数名称字符串有多个字符、一个dll有多个函数、一个exe有多个dll)
  8. 在5的基础上,继续F7单步,此时就要慢点了,快要到关键点了,要时刻关注寄存器窗口,肯定会出现xxx.yyy此种形式;发现1911执行后,eax中出现xxx.yyy

    脱壳实践笔记-动态空间填充IAT

  9. 这就是所谓获取API地址的地方(不管这个值是怎么出来的,我只知道,运行到此时,eax寄存器中有我想要的东西:原始的API地址)

06-OD脚本自动化修复IAT

(将真实API的地址添加到IAT,而非壳加密后的值

(要运行至壳OEP时再执行脚本,前面那个系统断点用OD的F9跳过

// 基础模版

// 1. 找到三个地址
MOV dwGetAPIAddr,004385BF
MOV dwWriteIATAddr, 004385F0
MOV dwOEP,00409486

// 2. 设置断点(设置之前先清除所有
BC    // 清除所有软件断点
BPHWC // 清除所有硬件断点
BPMC  // 清除所有内存断点

BPHWS dwGetAPIAddr, "x" //当执行到此地址时产生中断.
BPHWS dwWriteIATAddr, "x" //当执行到此地址时产生中断.
BPHWS dwOEP, "x" //当执行到此地址时产生中断.

// 3. 循环
LOOP_START:
  RUN   // 运行,即F9
  CMP dwGetAPIAddr,eip
  JNZ case1
  MOV dwTmp,eax// 将真实API地址保存至临时变量
  JMP LOOP_START
case1:
  CMP dwWriteIATAddr,eip  
  JNZ case2  
  MOV [edi],dwTmp// 将真实API地址填充至IAT表
  JMP LOOP_START
case2:
  CMP dwOEP,eip  
  JNZ LOOP_START  // 继续循环
  MSG "到达OEP!脚本结束"// 若达到OEP则结束
// 依据不同的壳,在基础版本上加以修改
// 1. 找到三个地址
MOV dwGetAPIAddr, 001A36        // 获取真实API地址(偏移
MOV dwWriteIATAddr, 000897    // 填充IAT(偏移
MOV dwOEP, 0047148B                    // OEP(真实地址
MOV dwBase,0047A37F                    // 壳申请的内存空间首地址(真实地址

// 2. 设置断点
BC    // 清除所有软件断点
BPHWC // 清除所有硬件断点
BPMC  // 清除所有内存断点

BPHWS dwOEP, "x"     //OEP设置断点,此地址不会变
BPHWS dwBase, "x" //申请内存空间返回基地址,是后面两个位置的基础

// 3. 循环
LOOP_START:
  RUN       // 继续运行,直至下个断点

  CMP dwBase,eip// 内存空间申请完成,返回基地址
  JNZ case0
  ADD dwGetAPIAddr,eax  // 基址+偏移 = 最终地址
  ADD dwWriteIATAddr,eax    
  BPHWS dwGetAPIAddr, "x" // 有了最终地址,再下断点
  BPHWS dwWriteIATAddr, "x" 
  JMP LOOP_START // 断点都下完了,继续执行
case0:
  CMP dwGetAPIAddr,eip
  JNZ case1
  MOV dwTmp,eax // 获取真实API地址,赋值给临时变量
  JMP LOOP_START // 继续执行
case1:
  CMP dwWriteIATAddr,eip  
  JNZ case2  
  MOV [edx],dwTmp// 将临时变量中的真实API地址填充到IAT
  JMP LOOP_START//继续
case2:
  CMP dwOEP,eip  // 若到达OEP,则前面都运行完,结束
  JNZ LOOP_START  // 否则继续执行
  MSG "到达OEP!脚本结束"// 弹窗,标示已结束

如图,修复完成(OEP是结束条件,所以正好运行至OEP

脱壳实践笔记-动态空间填充IAT

07-dump内存

  • 此时IAT表是正常的,dump下来后,通过此正常的IAT来修复输入表

    脱壳实践笔记-动态空间填充IAT

08-修复输入表

脱壳实践笔记-动态空间填充IAT

脱壳成功

脱壳实践笔记-动态空间填充IAT

09-参考

  • 15PB 脱壳课程
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

免责声明:
1.本站资源均来自互联网收集整理,不保证百分百完整无错、不提供任何技术支持;无法接受请勿购买或下载,如需完整程序,请到其官方地址购买正版使用,敬请谅解!
2.本站资源来自于网络,版权争议与本站无关,请务必在下载后24小时内删除,谢谢支持!
3.本站资源售价只是赞助,收取费用仅维持本站日常运营所需!由于资源具有较强的可复制性,可传播性,所以一经购买概不退款,请悉知!
4.本站所有源码资源仅供技术研究、学习交流使用,用户需自行确保其使用行为符合所在国家或地区的法律法规。我们不为任何非法用途提供支持,购买前请确认当地法律允许。
5.本站压缩包文件默认解压密码为:83ym.com

83源码 技术教程 脱壳实践笔记-动态空间填充IAT https://www.83ym.com/163.html

认准唯一TG:@ym830

常见问题
  • 站内所有资源,针对不同等级VIP会员可直接下载,特殊资源商品会注明是否免费,指会员所享有根据选择购买的会员选项所享有的特殊服务,具体以本站公布的服务内容为准。
查看详情
  • 按照我国的法律规定,运营网络棋牌首先需要成立一个注册正规备案的公司,然后申请网站备案、文网文、ICP等等,这些证件缺一不可。 一.注册公司 在当地工商进行注册,公司名称以“XX科技有限公司”为名,如:富裕棋牌经营范围填写“计算机软硬件、网络设备的设计开发与购销”。 二.域名及网站备案 在国内从事网站经营活动就必须经过相关部门的备案,因此棋牌运营商在购买了域名后,就要到当地网监局办理网站备案,或者请服务器提供商代为备案。 三.申请文网文 文网文全称为网络文化经营许可证,是从事经营性互联网文化活动所必需的资质。一般是需要到当地省一级(省、直辖市、自治区)的文化行政部门提出申请,并经由当地的文化行政部门合法批准。次资质要求申请公司注册资金必需达到1000万,并提供游戏版权证明文件。 四.申请ICP ICP又称为增值电信业务许可证,所有网络游戏运营商均需要办理ICP许可证,此证件要求公司注册资金1000万,需到当地市级通讯管理局办理。 五.申请文网游——游戏备案 根据《网络游戏管理暂行办法》(文化部第49号)的规定,国产网络游戏在上网运营之日起30日内应当按规定向国务院文化行政部门履行备案手续。 以上就是网络棋牌游戏正规运营所必需的资质证明。一般作为正规有实力的棋牌游戏开发公司,不光要具备所有的正规资质,而且会对投资者、代理商等合作伙伴给予相关指导和协助,与合作伙伴携手共赢!
查看详情

相关文章

猜你喜欢
官方客服团队

为您解决烦忧 - 24小时在线 专业服务