首页 > 其他分享 >♂hook初探♂(持续更新)

♂hook初探♂(持续更新)

时间:2024-12-29 12:52:08浏览次数:6  
标签:函数 flag 地址 更新 hook WriteFile 初探 input sub

主要是从攻防世界中的easyhook中学习,感觉好神奇.

参考了以下博客:

攻防世界逆向高手题之EASYHOOK-CSDN博客

RE套路/从EASYHOOK学inline hook - c10udlnk - 博客园

先贴源码:

 sub_401370(aPleaseInputFla);
   scanf("%31s", input_flag);
  if ( strlen(input_flag) == 19 )
  {
    sub_401220();		//未知名函数,一开始当然不会注意
    v4 = CreateFileA(FileName, 0x40000000u, 0, 0, 2u, 0x80u, 0);		//创建文件函数
    WriteFile(v4, input_flag, 19u, &NumberOfBytesWritten, 0);		//写入函数,这些系统函数通常不是重点,如果影响理解代码的话直接查API即可,  WriteFile(句柄, 写入字符串, 写入字节, 指向写入直接的指针, 0)
    sub_401240(input_flag, &NumberOfBytesWritten);
    if ( NumberOfBytesWritten == 1 )	//判断函数
      sub_401370(aRightFlagIsYou);
    else
      sub_401370(aWrong);
    system(Command);
    result = 0;
  }
  else
  {
    sub_401370(aWrong);
    system(Command);
    result = 0;
  }
  return result;
}

然后要注意sub_401220():

int sub_401220()
{
  HMODULE v0; // eax
  DWORD v2; // eax

  v2 = GetCurrentProcessId();			//系统函数,获取进程ID,就是当前程序的ID
  hProcess = OpenProcess(0x1F0FFFu, 0, v2);		//系统函数,返回现有进程对象的句柄。
  v0 = LoadLibraryA(LibFileName);			//系统函数,将指定的可执行模块映射到调用进程的地址空间,这里LibFileName双击跟踪存入的是kernel32.dll模块,就是导入了它
  *(_DWORD *)WriteFile_0 = GetProcAddress(v0, ProcName);		//系统函数,返回指定的导出动态链接库(DLL)函数的地址。 ProcName存放的是WriteFile函数名,也就是导入WriteFile函数。
  lpAddress = *(LPVOID *)WriteFile_0;	//获取WriteFile函数地址
  if ( !*(_DWORD *)WriteFile_0 )		//无用函数,因为kernel32.dll模块的WriteFile函数一定存在
    return sub_401370(&unk_40A044);	//sub_401370函数类型puts函数,是通过主函数分析得到的,&unk_40A044处的字符串是获取原API入口地址出错,不用管他。
  unk_40C9B4 = *(_DWORD *)lpAddress;		//这里获取WriteFile函数的地址
  *((_BYTE *)&unk_40C9B4 + 4) = *((_BYTE *)lpAddress + 4);		//这里地址后四位也保持一样,不知道有什么用
  aHook1 = 0xE9;		//这里连同第二句是我犯下的第二个错误:这里转十六进制不是E9,是JMP的机器码指令,而不一开始并没有机器码的相关知识。
  aHook2 = (char *)sub_401080 - (char *)lpAddress - 5;		//这里是一个偏移地址,而且还是满足HOOK的连续地址。之所以这样写是因为汇编语言JMP address被编译后会变成机器指令码,E9  偏移地址,偏移地址=目标地址-当前地址-5(jmp和其后四位地址共占5个字节)。所以前面直接用E9,这里直接用偏移地址就省去编译生成机器码那一步。这也是HOOK的原型。
  return sub_4010D0();		返回一个函数,继续跟踪,因为前面并没有什么修改程序的行为
}

主要看下面,可以看到这里搞了jmp,而且注意aHook1和aHook2(这里是我修改过的名字)是连续的,也就是说,可以看成jmp sub_401080.

接下来看sub_4010D0():

BOOL sub_4010D0()
{
  DWORD v1; // [esp+4h] [ebp-8h] BYREF
  DWORD flOldProtect; // [esp+8h] [ebp-4h] BYREF

  v1 = 0;
  VirtualProtectEx(hProcess, lpAddress, 5u, 4u, &flOldProtect);
  WriteProcessMemory(hProcess, lpAddress, &aHook1, 5u, 0);//修改
  return VirtualProtectEx(hProcess, lpAddress, 5u, flOldProtect, &v1);
}
//VirtualProtectEx(进程,修改地址,修改区域大小,[修改其中权限,1,2,4对应执行,写,读],一个保存修改前权限的变量 ),所以这三行作用是对lpAddress所存储的地址处进行了5字节的权限修改操作,先改成读写再往此处写入以前面E9 偏移量地址处的5个字节(即上面的跳板指令),最后恢复权限,完成修改。

这就是hook,劫持程序流.

那么现在WriteFile被改写成了jmp也就是跳到sub_401080,我们看看它:

int __stdcall sub_401080(
        HANDLE hFile,
        LPCVOID lpBuffer,
        DWORD nNumberOfBytesToWrite,
        LPDWORD lpNumberOfBytesWritten,
        LPOVERLAPPED lpOverlapped)
{
  int v5; // ebx

  v5 = sub_401000(lpBuffer, nNumberOfBytesToWrite); //加密函数
  sub_401140(); //这个是把WriteFile恢复的函数
  WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
  if ( v5 )
    *lpNumberOfBytesWritten = 1;
  return 0;
}

sub_401000:

int __cdecl sub_401000(int input_flag, int _19)
{
  char i; // al
  char v3; // bl
  char v4; // cl
  int v5; // eax

  for ( i = 0; i < _19; ++i )
  {
    if ( i == 18 )
    {
      *(_BYTE *)(input_flag + 18) ^= 19u;       // 这里犯下第五个错误,写脚本时这种单独的if语句应该直接在外面单独成行,不然就要多写几个elif语句了,界面就会很乱!
    }
    else
    {
      if ( i % 2 )
        v3 = *(_BYTE *)(i + input_flag) - i;
      else
        v3 = *(_BYTE *)(i + input_flag + 2);
      *(_BYTE *)(i + input_flag) = i ^ v3;
    }
  }
  v4 = 0;
  if ( _19 <= 0 )                               // 不会小于等于,所以不会在这里返回
    return 1;
  v5 = 0;
  while ( aAjygkfm[v5] == *(_BYTE *)(v5 + input_flag) )		//这里犯下第四个错误,前面的加密逻辑中我们没有可以参照的字符串,因为flag是推出来的,而真正的字符串在后面,所以逆向逻辑时首先要找到非输入的字符串才行!这里双击跟踪 aAjygkfm等于ajygkFm.\x7f_~-SV{8mLn
  {
    v5 = ++v4;
    if ( v4 >= _19 )
      return 1;
  }
  return 0;
}

写脚本,可得flag为:"-lag{Ho0k_w1th_Fun}"

标签:函数,flag,地址,更新,hook,WriteFile,初探,input,sub
From: https://www.cnblogs.com/T0fV404/p/18638633

相关文章

  • 试题转excel;word转excel;大风车excel(1.1更新)
    最近更新了大风车excel1.1版本主要优化在算法层面:1.0版本试题解析的成功率为95%,现在1.1版本已经优化到解析成功率为99% 一、问题描述一名教师朋友,偶尔会需要整理一些高质量的题目到excel中以往都是手动复制搬运,几百道题几乎需要一个下午的时间关键这些事,枯燥无聊费......
  • [4431] 17 部署初探:为什么一般不在开发环境下部署代码?
    这节课我们将进入前端效率工程化的第三个模块——部署效率篇。本模块主要讨论两个方面的问题:第一个是在前端项目的构建部署流程里,除了使用构建工具执行构建之外,还有哪些因素会影响整个部署流程的工作效率?第二个是在部署系统中进行项目构建时,又会面临哪些和环境相关的问题和优化方......
  • 【更新至2025年新版本】超详细PyCharm安装教程及基本使用!
    PyCharm是一款PythonIDE,其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如,调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外,该IDE提供了一些高级功能,以用于支持Django框架下的专业Web开发。文章目录一、P......
  • 【gopher的java学习笔记】Spring Boot Starter初探
    转到java这边后,这天需要搭一个java的webservice出来,如果是以前golang的话,那我就可以非常熟练的用gin搭建一个webservice出来,核心逻辑就是写好一些rest接口实现后再加上最为灵魂的一句://启动Gin服务器在8080端口router.Run(":8080")那来到java这边,我第一反应......
  • Win11频繁自动关机,更新驱动和系统无效
    新购买的主机Win11系统频繁自动关机。厂商400开单联系售后说是需要重装系统,在微软官网下载全新系统后,更新到最新版本windows,同样自动关机。查看windows日志,进行测试调整有如下一个信息有错误。“安全启动无法更新,参数错误”解决办法:打开注册表:计算机\HKEY_LOC......
  • 【WPF】WPF 双向绑定中的 SelectedItem 与 ViewModel 属性更新机制详解
     在WPF开发中,ListBox等控件常用于显示绑定的数据集合,其中ItemsSource绑定的数据源,在没有显式设置 Mode 属性时,默认为单向绑定,它将数据源集合的内容传递给 ListBox,但不会反向更新数据源。而SelectedItem ,默认情况下它的绑定是双向的。这意味着当用户在 ListBox 中......
  • Apifox 12月更新|接口的测试覆盖情况、测试场景支持修改记录、迭代分支能力升级、自定
    Apifox新版本上线啦!!!在快速迭代的开发流程中,接口测试工具的强大功能往往决定了项目的效率和质量。而Apifox在12月的更新中,再次引领潮流,推出了一系列重磅功能!测试覆盖情况分析、场景修改记录、自定义权限等功能的加入,为开发者和测试人员带来了新的工作方式。这些功能具体......
  • uni-app 版本更新
    APP检测版本并升级//应用IdconstcurrentAppId=plus.runtime.appid;//获取当前应用版本号constcurrentVersion=plus.runtime.versionCode;//这里可以替换为你的服务器端接口,获取应用最新版本信息uni.request({url:'https://your-api-server.com/che......
  • 向服务器更新文件
    //下载版本///<summary>///下载版本///</summary>///<paramname="FilePath">服务器文件地址完整</param>///<paramname="downLoadPath">下载到本地地址</param>///<returns></returns>......
  • 23种设计模式【持续更新】
    1.软件设计原则2.创建型设计模式3.结构型设计模式4.行为型设计模式15.行为型设计模式2......