从零开始学习破解(第三天)

发布于 2022-04-26  64 次阅读 百度未收录


开搞开搞

看了会od的汇编代码,查了会百度,反正就那么几条常用指令,反而更重要的是各个寄存器的作用以及保存的内容,等用到的时候再说吧,只要玩的久,迟早能学会。

开搞开搞,虽然没有系统的学习过,但是我还是感觉,实践出真理,多用,多查,学的最快了。

程序所有的代码,都是汇编形式写入的,那么就是说,我们可以直接修改汇编代码,来实现修改程序,类似网站上直接F12修改。首先打开OD,找到要修改的地方,说实话,最难的应该也就是这里了。

不过咱们可以作弊,因为有源码,直接vs打断点,查看反汇编。

那咱们尝试一下,修改错误次数,目前每次次数+1,咱们给修改成16很明显,这里有个+1给修改成+16就OK了。

记一下地址0x12267F1然后dll中试着修改一下。

注意的是,要给之前的注释掉,因为每次的偏移都是不一样的,除非没有修改过exe。不过很可惜,我这边修改了一下提示内容。哈哈。代码如下:

#define CALLOFFSET (0x12267F1)
VOID ModMemory() 
{
    BYTE modcode[3] = { 0 };
    modcode[0] = 0x83;
    modcode[1] = 0xC0;
    modcode[2] = 0x10;

	//覆盖式写入
	if (WriteProcessMemory(GetCurrentProcess(), (LPVOID)(CALLOFFSET), modcode, 3, NULL) == 0) {
		MessageBox(NULL, "写入内存失败", 0, 0);
		return;
	}
}

F3试试看

果然没问题。vs调试一下看看

可以看到vs中的反汇编也成功的被修改。

让软件忽略输入内容

要实现这个功能,那么就需要覆盖其中一段代码,让他调用自己的功能。大致想法如下:

查看反汇编,看到这个调用系统函数的,刚好是5个字节,那么就给这个替换掉。

DWORD peax = 0;

// 指向了需要修改的地址
// 回跳地址就是这个地址+5
// 调用GetDlgItemText的地址
DWORD GetDlgItemTextAddr = 0x00A1681E;
DWORD dwBack = GetDlgItemTextAddr + 5;


char* pStr = NULL;
DWORD dwBuffAddr = 0;
void __declspec(naked) myfun()
{
	__asm
	{
		mov peax, eax
	}

	// eax 中保存了一个指针 这个指针指向了字符串的缓冲区
	dwBuffAddr = *(DWORD*)(peax);
	pStr = (char*)(dwBuffAddr);
	//pStr = *pStr;
	memmove(pStr, "123\0", 4);

	// 跳转回原来的逻辑
	__asm
	{
		add esp, 0x8
		jmp dwBack
	}
};

int OnInit()
{
	MessageBox(0, "成功潜入敌人内部!", "报告主人", NULL);
	HANDLE hand = GetModuleHandle("login.exe");
	if (!hand)
	{
		MessageBox(0, "查找主句柄失败!", "报告主人", NULL);
		return 0;
	}
	// 变量区从某个区后面进行偏移
	//ModCount((DWORD)hand + CALLOFFSET)

	// 代码区地址从0开始偏移
	//ModMemory(CALLOFFSET);

	// 
	ModMemory2(GetDlgItemTextAddr);
	return 0;
}

随便输入一下试试看。

果然已经替换掉了。对了,login.exe代码改了一下提示,现在代码如下:

void CloginDlg::OnBnClickedOk()
{
	m_nCount++;
	CString str;
	GetDlgItemText(IDC_EDIT1, str);
	if (str != _T("123"))
	{
		CString str2;
		str2.Format("密码错误 %d 次", m_nCount);
		MessageBox(str2);
		return ;
	}
	CString str3;
	str3.Format("密码验证通过,恭喜你成功登陆你输入的密码是[%s]", str);
	MessageBox(str3);
	return;
	// TODO: 在此添加控件通知处理程序代码
	CDialogEx::OnOK();
}

这个不够高级。下面就来尝试一下,昨天说的,调用软件的功能。

hook直接调用软件的功能

按照前面的知识,感觉调用软件的功能就比较简单了。为了降低难度,咱们自己写一个函数。

void ShowMessagebox(int nID)
{
	CString str;
	str.Format("这里是弹窗%d", nID);
	MessageBox(0, str, "报告主人", 0);
}

void CloginDlg::OnBnClickedCancel()
{
	ShowMessagebox(255);
	// TODO: 在此添加控件通知处理程序代码
	CDialogEx::OnCancel();
}

在取消按钮中调用一下。

看一下反汇编。

记录这个函数的地址,然后再注入的时候调用一下。

DWORD dwOnOKaddr = 0x0F2DC7E;

// 调用软件的功能
void CallFunction()
{
	__asm
	{
		push 123
		call dwOnOKaddr
		add esp,0x4
	}
}

int OnInit()
{
	MessageBox(0, "成功潜入敌人内部!", "报告主人", NULL);
	HANDLE hand = GetModuleHandle("login.exe");
	if (!hand)
	{
		MessageBox(0, "查找主句柄失败!", "报告主人", NULL);
		return 0;
	}
	CallFunction();
	return 0;
}

F3试一下。直接就弹出来了,说明没问题。

研究到此为止,我感觉我可以去找个工作了,嘿嘿。


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。