能力值:
( LV2,RANK:10 )
2 楼
GetLastError 返回 说是内存分配访问无效
能力值:
( LV2,RANK:10 )
3 楼
经过测试发现不是打开自身不成功,是打开所有文件都不成功,报错都是getlasterror 返回0x3e6。
我的shellcode运行在dll文件新增加的一个节中,先执行shellcode后jmp回OEP,是不是由于shellcode运行并非归属于任何进程的主线程所致呢?
期待朋友们的关注,哪怕您不确定答案,也非常欢迎您说出自己的想法,大家讨论讨论也好!
能力值:
( LV2,RANK:10 )
4 楼
自己顶。。。。。。。。。。。。。。。。。。。。。
能力值:
( LV2,RANK:10 )
6 楼
你的shellcode是放在dll文件中?shellcode里用到的API函数地址你是怎么获得的?把包含CreateFileA这段代码发上来看看
能力值:
( LV7,RANK:100 )
7 楼
你的问题我遇到过,好像!但是,你说的不是很清楚,把程序贴出来,可以分析下一起!
能力值:
( LV2,RANK:10 )
8 楼
帮顶,同求解答
能力值:
( LV2,RANK:10 )
9 楼
shellcode代码如下:
获取API地址就从PEB里面查出来的,很常用的手法
_asm pushad
_asm mov [ebp-4h], ebx //保存入口点地址到[ebp-504h]
_asm mov eax, fs:0x30 //PEB的地址
_asm mov esi , 0x30
_asm mov eax, [eax + 0x0c]
_asm mov esi, [eax + 0x1c]
_asm lodsd
_asm mov eax, [eax + 0x08] //eax=kernel32.dll的基地址
_asm mov edi, eax
_asm mov ebp, eax
_asm mov eax, [ebp + 3ch]
_asm mov edx, [ebp + eax + 78h]
_asm add edx, ebp
_asm mov ecx, [edx + 18h]
_asm mov ebx, [edx + 20h]
_asm add ebx, ebp
search:
_asm dec ecx
_asm mov esi, [ebx + ecx * 4]
_asm add esi, ebp
_asm mov eax, 0x50746547
_asm cmp [esi], eax //比较"GetProcAddress"
_asm jne search
_asm mov eax, 0x41636f72
_asm cmp [esi + 4], eax
_asm jne search
_asm mov ebx, [edx + 24h]
_asm add ebx, ebp
_asm mov cx, [ebx + ecx * 2]
_asm mov ebx, [edx + 1ch]
_asm add ebx, ebp
_asm mov eax, [ebx + ecx * 4]
_asm add eax, ebp //eax保存的就是GetProcAddress的地址
//为局部变量分配空间
_asm push ebp
_asm sub esp, 600h
_asm mov ebp, esp
//查找LoadLibrary的地址
_asm mov [ebp + 40h], eax //把GetProcAddress的地址保存到ebp + 40中
//开始查找GetModuleFileName的地址,先构造“GetModuleFileNameA\0”
_asm push 0x0
_asm push DWORD PTR 0x41656d61
_asm push DWORD PTR 0x4e656c69
_asm push DWORD PTR 0x46656c75
_asm push DWORD PTR 0x646f4d74
_asm push WORD PTR 0x6547
_asm push esp//压入“GetModuleFileNameA\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h]
_asm mov [ebp + 3ch],eax //保存GetModuleFileNameA的地址到ebp+3c //开始查找CreateFileA的地址,先构造“CreateFileA\0”
_asm push 0x0
_asm push DWORD PTR 0x0041656c
_asm push DWORD PTR 0x69466574
_asm push DWORD PTR 0x61657243
_asm push esp//压入“CreateFileA\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 38h],eax //保存CreateFileA的地址到ebp + 38 //开始查找WinExec的地址,先构造“WinExec\0”
_asm push 0x0
_asm push DWORD PTR 0x00636578
_asm push DWORD PTR 0x456e6957
_asm push esp//压入“WinExec\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 34h],eax //保存WinExec的地址到ebp + 34 //开始查找GetFileSize
_asm push 0x0
_asm push DWORD PTR 0x00657a69
_asm push DWORD PTR 0x53656c69
_asm push DWORD PTR 0x46746547
_asm push esp//压入“GetFileSize\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 30h],eax //保存GetFileSize的地址到ebp + 30
//开始查找SetFilePointer
_asm push 0x0
_asm push DWORD PTR 0x7265746e
_asm push DWORD PTR 0x696f5065
_asm push DWORD PTR 0x6c694674
_asm push WORD PTR 0x6553
_asm push esp//压入“SetFilePointer\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 44h],eax //保存SetFilePointer的地址到ebp + 44 //开始查找ReadFile
_asm push 0x0
_asm push DWORD PTR 0x656c6946
_asm push DWORD PTR 0x64616552
_asm push esp//压入“ReadFile\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 2ch],eax //保存ReadFile的地址到ebp + 2c
//开始查找CloseHandle
_asm push 0x0
_asm push DWORD PTR 0x00656c64
_asm push DWORD PTR 0x6e614865
_asm push DWORD PTR 0x736f6c43
_asm push esp//压入“CloseHandle\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 28h],eax //保存CloseHandle的地址到ebp + 28
//开始查找WriteFile
_asm push DWORD PTR 0x00656c69
_asm push DWORD PTR 0x46657469
_asm push WORD PTR 0x7257
_asm push esp//压入“WriteFile\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 24h],eax //保存WriteFile的地址到ebp + 24
// 开始查找_lopen
_asm push 0x0
_asm push 0x00006e65
_asm push 0x706f6c5f
_asm push esp//压入“_lopen\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 20h],eax //保存_lopen的地址到ebp + 20
// 开始查找GetLastError
_asm push 0x0
_asm push 0x726f7272
_asm push 0x45747361
_asm push 0x4c746547
_asm push esp//压入“GetLastError\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm mov [ebp + 1ch],eax //保存GetLastError的地址到ebp + 1c 这里开始创建文件,尝试过各种创建方法,都是报错
_asm push 0x0
_asm push DWORD PTR 0x6578652e
_asm push DWORD PTR 0x706c6568 //help.exe
_asm mov [ebp+500h],esp //文件名
_asm push NULL
_asm push 0
_asm push CREATE_ALWAYS
_asm push NULL
_asm push FILE_SHARE_READ
_asm push GENERIC_WRITE
_asm push [ebp+500h]
_asm call [ebp + 38h]//打开文件
_asm call [ebp + 1ch]
_asm mov [ebp + 4],eax//保存文件句柄到[ebp + 4]
_asm push OF_READWRITE
_asm push [ebp + 500h]
_asm call [ebp + 20h]
能力值:
( LV2,RANK:10 )
10 楼
你先借助VS带的Depends工具,查看一下kernel32.dll的基址,各个函数的地址有没有获取正确,然后你保存在的 [ebp+XXh]有没有正确的写入,call之前再查看一下内存[ebp+XXh]
另外你第4条指令
_asm mov esi , 0x30 我认为是多余的,第3条指令应该是:_asm mov eax, fs:[0x30]
能力值:
( LV2,RANK:10 )
11 楼
还有
_asm push [ebp+500h] 就是把你在堆栈中构造的字符串“help.exe”压栈吧?
CreateFileA函数的第一参数 是路径,你传递进堆栈的参数只是“help.exe”,这样能创建成功吗?
能力值:
( LV2,RANK:10 )
12 楼
建议楼主先借助VC自带的depends检查你获取的各个函数地址,然后再call之前再检查一遍;
CreateFileA的第一参数你改成“C:\\help.exe”或者其他的路径,调用成功后,就是平衡堆栈的问题了,不然程序执行完shellcode后会崩溃!我看你上面写的有点乱...
小弟最近刚写完一个shellcode,上面是我的心得体会...
能力值:
( LV7,RANK:100 )
13 楼
首先,对于你的代码我提出一个建议,你的内嵌汇编太长的话,你可以使用
_asm
{
pushad
popad
}
这样子,可以大大提高效率!
你的代码之所以失败,是由于你的堆栈被破坏了。如果你能够注意到堆栈的平衡的话,你的代码就没有问题了。
还有,EBP是用来访问局部变量,以及参数变量的,而不是用来“存放Kernel32的基址”的。如果实在要用,要记得PUSH ,POP。
_asm pushad
//为局部变量分配空间
_asm push ebp
_asm sub esp, 600h
_asm mov ebp, esp
_asm mov [ebp+504h], ebx //保存入口点地址到[ebp+504h]
_asm mov eax, fs:[0x30] //PEB的地址
_asm mov eax, [eax + 0x0c]
_asm mov esi, [eax + 0x1c]
_asm lodsd
_asm mov eax, [eax + 0x08] //eax=kernel32.dll的基地址
_asm mov edi, eax
_asm push ebp //下一句要改变EBP的值,之前必须先保存下来
_asm mov ebp, eax//ebp为kernel32.dll的基址
_asm mov eax, [ebp + 3ch]
_asm mov edx, [ebp + eax + 78h]
_asm add edx, ebp
_asm mov ecx, [edx + 18h]
_asm mov ebx, [edx + 20h]
_asm add ebx, ebp
search:
_asm dec ecx
_asm mov esi, [ebx + ecx * 4]
_asm add esi, ebp
_asm mov eax, 0x50746547
_asm cmp [esi], eax //比较"GetProcAddress"
_asm jne search
_asm mov eax, 0x41636f72
_asm cmp [esi + 4], eax
_asm jne search
_asm mov ebx, [edx + 24h]
_asm add ebx, ebp
_asm mov cx, [ebx + ecx * 2]
_asm mov ebx, [edx + 1ch]
_asm add ebx, ebp
_asm mov eax, [ebx + ecx * 4]
_asm add eax, ebp //eax保存的就是GetProcAddress的地址
_asm pop ebp//恢复EBP //查找LoadLibrary的地址
_asm mov [ebp + 40h], eax //把GetProcAddress的地址保存到ebp + 40中
//开始查找GetModuleFileName的地址,先构造“GetModuleFileNameA\0”
_asm push 0x0
_asm push DWORD PTR 0x41656d61
_asm push DWORD PTR 0x4e656c69
_asm push DWORD PTR 0x46656c75
_asm push DWORD PTR 0x646f4d74
_asm push WORD PTR 0x6547
_asm push esp//压入“GetModuleFileNameA\0”
_asm push edi//kernel32基址
_asm call [ebp + 40h]
_asm add esp,0x16//必须平衡堆栈,因为之前为了构造GetModuleFileNameA,压入了许多字符
_asm mov [ebp + 3ch],eax //保存GetModuleFileNameA的地址到ebp+3c
//开始查找CreateFileA的地址,先构造“CreateFileA\0”
_asm push 0x0
_asm push DWORD PTR 0x0041656c
_asm push DWORD PTR 0x69466574
_asm push DWORD PTR 0x61657243
_asm push esp//压入“CreateFileA\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x10
_asm mov [ebp + 38h],eax //保存CreateFileA的地址到ebp + 38 //开始查找WinExec的地址,先构造“WinExec\0”
_asm push 0x0
_asm push DWORD PTR 0x00636578
_asm push DWORD PTR 0x456e6957
_asm push esp//压入“WinExec\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x0C
_asm mov [ebp + 34h],eax //保存WinExec的地址到ebp + 34 //开始查找GetFileSize
_asm push 0x0
_asm push DWORD PTR 0x00657a69
_asm push DWORD PTR 0x53656c69
_asm push DWORD PTR 0x46746547
_asm push esp//压入“GetFileSize\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x10
_asm mov [ebp + 30h],eax //保存GetFileSize的地址到ebp + 30
//开始查找SetFilePointer
_asm push 0x0
_asm push DWORD PTR 0x7265746e
_asm push DWORD PTR 0x696f5065
_asm push DWORD PTR 0x6c694674
_asm push WORD PTR 0x6553
_asm push esp//压入“SetFilePointer\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x12
_asm mov [ebp + 44h],eax //保存SetFilePointer的地址到ebp + 44 //开始查找ReadFile
_asm push 0x0
_asm push DWORD PTR 0x656c6946
_asm push DWORD PTR 0x64616552
_asm push esp//压入“ReadFile\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0xC
_asm mov [ebp + 2ch],eax //保存ReadFile的地址到ebp + 2c //开始查找CloseHandle
_asm push 0x0
_asm push DWORD PTR 0x00656c64
_asm push DWORD PTR 0x6e614865
_asm push DWORD PTR 0x736f6c43
_asm push esp//压入“CloseHandle\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x10
_asm mov [ebp + 28h],eax //保存CloseHandle的地址到ebp + 28
//开始查找WriteFile
_asm push DWORD PTR 0x00656c69
_asm push DWORD PTR 0x46657469
_asm push WORD PTR 0x7257
_asm push esp//压入“WriteFile\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x0A
_asm mov [ebp + 24h],eax //保存WriteFile的地址到ebp + 24
// 开始查找_lopen
_asm push 0x0
_asm push 0x00006e65
_asm push 0x706f6c5f
_asm push esp//压入“_lopen\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x0C
_asm mov [ebp + 20h],eax //保存_lopen的地址到ebp + 20
// 开始查找GetLastError
_asm push 0x0
_asm push 0x726f7272
_asm push 0x45747361
_asm push 0x4c746547
_asm push esp//压入“GetLastError\0”
_asm push edi//kernel32基址
_asm call[ebp + 40h] //GetProcAddress
_asm add esp,0x10
_asm mov [ebp + 1ch],eax //保存GetLastError的地址到ebp + 1c //这里开始创建文件,尝试过各种创建方法,都是报错
_asm push 0x0
_asm push DWORD PTR 0x6578652e
_asm push DWORD PTR 0x706c6568 //help.exe
_asm mov [ebp+500h],esp //文件名
_asm push NULL
_asm push 0
_asm push CREATE_ALWAYS
_asm push NULL
_asm push 0
_asm push GENERIC_WRITE
_asm push [ebp+500h]
_asm call [ebp + 38h]//打开文件 CreateFileA
_asm add esp,0xC
// _asm call [ebp + 1ch] //GetLastError
_asm mov [ebp + 4],eax//保存文件句柄到[ebp + 4]
// _asm push OF_READWRITE
// _asm push [ebp + 500h]
// _asm call [ebp + 20h]
//返回后进行最后的局部变量释放
_asm add esp ,600h
_asm pop ebp
_asm popad
能力值:
( LV2,RANK:10 )
14 楼
首先感谢追风傲雪,
不过你说的问题我以前也都怀疑过,但都被我排除了,
首先是kernel32的地址,这个shellcode我每次写完以后都是在olldbg中调试的,每次都看得到它的地址和相关的API正确使用。
还有_asm mov esi , 0x30这一句,由于我是在VC中内嵌汇编的,所以这个写法没问题的。
最后是文件名“help.exe”
这个我和你想的一样也是写了绝对路径,但是仍然报错。
这个报错跟写法或者语法什么的关系似乎不大了,shellcode由于我改了太多次了,所以现在看着有点乱。
有个情况我可能没提到,就是调用GetModuleFileName、LoadLibraryA或者GetLastError这样的API是没问题的。
能力值:
( LV2,RANK:10 )
15 楼
把绝对路径“C:\\help.exe”换成“C:\help.exe”试试
因为C++中的“\\”指的是“\”, 汇编应该没有这个格式
能力值:
( LV2,RANK:10 )
16 楼
_asm push NULL _asm push 0 _asm push CREATE_ALWAYS _asm push NULL _asm push FILE_SHARE_READ _asm push GENERIC_WRITE _asm push [ebp+500h] _asm call [ebp + 38h]//打开文件
你的dwFlagsAndAttributes参数怎么是0?
MSDN里没有发现有0的值,你换成0x80试试
下面摘自MSDN:
Attribute Meaning
FILE_ATTRIBUTE_ARCHIVE
32 (0x20) The file should be archived. Applications use this attribute to mark files for backup or removal.
FILE_ATTRIBUTE_ENCRYPTED
16384 (0x4000) The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is the default for newly created files and subdirectories. For more information, see File Encryption.
This flag has no effect if FILE_ATTRIBUTE_SYSTEM is also specified.
FILE_ATTRIBUTE_HIDDEN
2 (0x2) The file is hidden. Do not include it in an ordinary directory listing.
FILE_ATTRIBUTE_NORMAL
128 (0x80) The file does not have other attributes set. This attribute is valid only if used alone.
FILE_ATTRIBUTE_OFFLINE
4096 (0x1000) The data of a file is not immediately available. This attribute indicates that file data is physically moved to offline storage. This attribute is used by Remote Storage, the hierarchical storage management software. Applications should not arbitrarily change this attribute.
FILE_ATTRIBUTE_READONLY
1 (0x1) The file is read only. Applications can read the file, but cannot write to or delete it.
FILE_ATTRIBUTE_SYSTEM
4 (0x4) The file is part of or used exclusively by an operating system.
FILE_ATTRIBUTE_TEMPORARY
256 (0x100) The file is being used for temporary storage.
For more information, see the Caching Behavior section of this topic.
缺省值:
The file or device attributes and flags, FILE_ATTRIBUTE_NORMAL being the most common default value for files.
能力值:
( LV2,RANK:10 )
17 楼
感谢MatrixNERO这位朋友,
首先我每次都用 _asm 前缀实属无奈,因为用大括号括起来编译报错,这个问题我没追究过。
关于ebp寄存器使用的问题这个属于个人习惯了,而且我也有对应的push和pop
堆栈平衡这个问题楼上2位都提到过,我是应该仔细的关注一下了,不过这些细节我总是想在完成实质内容(也就是功能)之后再仔细的找补。
最后再次感谢大家的建议,回头我修改一下以后再进行测试。
能力值:
( LV2,RANK:10 )
18 楼
CreateFileA的参数我换过无数次了,各种组合我都试验过。 你看到的是我试尽各种方式传参失败后,故意传有问题的参数,然后跟到底层去看ZwCreateFile的反应一个版本,其它测试代码我都没有粘进来。
能力值:
( LV2,RANK:10 )
19 楼
楼主尽快解决问题哈...
我都替你着急,平衡堆栈在OD里调试挺有意思的,使用VC内联汇编可以在代码中任意位置加入
__asm
{
int 3
}
中断程序,好把OD弹出来调试,很方便的
祝楼主尽快解决问题!
能力值:
( LV2,RANK:10 )
20 楼
好的,谢谢,现在手里没代码,明天修改一下看看
能力值:
( LV2,RANK:10 )
21 楼
细节很重要啊!我每次都压栈esp忘记了这个寄存器和其他寄存器的区别,导致堆栈被破坏无法正常运行,现在仔细修改后问题解决了!
再次感谢各位朋友的相助!
能力值:
( LV2,RANK:10 )
22 楼
问题出在esp寄存器?
呵呵,恭喜楼主解脱了!