|
在网上看到一篇文章“修改NTLDR添加Boot级开机密码”,觉得很有意思,本人是菜鸟,谁能给出一个修改后的ntldr。或者给出一个制作的视频教程就更好了。
请在百度“修改NTLDR添加Boot级开机密码”了解那篇文章。
文章中插入的16位汇编源码:
;#Mode=COM
.model tiny
.CODE
start:
;保存寄存器内容,避免影响系统加载
push ax
push bx
push cx
push dx
push si
push di
entry:
;设置ds=cs,以便后面定位字符
mov ax,cs
mov ds,ax
call sc
;显示输入密码的提示字符串
mov ax,1234h
call print
;正确密码的字符串地址放入si
mov si,2341h
xor di,di
lp:
;取得用户输入
call getkey
cmp al,ds:[si]
je short byte_right
;本字符正确则增加计数,存于di
inc di
byte_right:
;显示一个*
mov al,'*'
call putchar
inc si
mov al,ds:[si]
cmp al,0
je short check
;输入未完成,继续获取用户输入
jmp short lp
check:
;输入完成,检查密码是否完全正确
cmp di,0
;正确则程序退出,代码权交给系统,继续引导
je short succ
;不正确则显示密码错误提示,并重新要求输入
mov ah,2
mov bh,0
mov dh,2
mov dl,0
int 10h
mov ax,4321h
call print
call getkey
jmp short entry
succ:
;恢复寄存器内容
pop di
pop si
pop dx
pop cx
pop bx
pop ax
;跳回原始地址
mov ax,4231h
jmp ax
ret
sc proc ;清屏
mov ah,0h
mov al,2h
int 10h ;设置显示模式
ret
sc endp
putchar proc ;就是C里面的putchar(),入口参数al=the const char
mov ah,10
mov cx,1
mov bh,0h
int 10h
mov ah,3
mov bh,0
int 10h
mov ah,2
cmp dl,79
je short line_over
inc dl
int 10h
ret
line_over:
mov dl,0
inc dh
int 10h
ret
putchar endp
getkey proc ;相当于inkey$,出口al->按键的ASCII
mov ah,0h
int 16h
ret
getkey endp
print proc ;显示一个字符串,以'\0'结尾,入口参数,ax=const char *
mov si,ax
ff:
mov al,ds:[si]
cmp al,0
je string_over
call putchar
inc si
jmp ff
string_over:
ret
print endp
pass db 'PASSWORD',0,0,0,0
Ask db 'Enter password:',0
fail db 'Wrong.',0
END
插入的C源程序为:
#include <stdio.h>
#include <Windows.h>
#define MAX_SHELLCODE_SIZE 200
int OFFSET_TIPS_MOV;
int OFFSET_PWD_MOV;
int OFFSET_WARN_MOV;
int OFFSET_PWD;
int OFFSET_STR_TIPS;
int OFFSET_STR_WARN;
int OFFSET_JMP_MOV;
WORD ORG_JMP_CODE;
BOOL EnablePrivilege()
{
TOKEN_PRIVILEGES tkp;
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
// 修改进程权限
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL);
// 通知系统修改进程权限
return (GetLastError()== ERROR_SUCCESS);
}
HANDLE OpenCom()
{
HANDLE hCom;
wchar_t szCom[MAX_PATH];
// 打开COM程序
ZeroMemory(szCom, MAX_PATH * sizeof(wchar_t));
GetCurrentDirectory(MAX_PATH, szCom);
wcscat(szCom, L"\\chkpwd.com");
hCom = CreateFile(szCom, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
return hCom;
}
HANDLE OpenNTLDR()
{
HANDLE hNTLDR;
wchar_t szNTLDR[MAX_PATH];
// 打开NTLDR
ZeroMemory(szNTLDR, MAX_PATH * sizeof(wchar_t));
GetSystemDirectory(szNTLDR, MAX_PATH);
ZeroMemory(szNTLDR + 2, (MAX_PATH - 2) * sizeof(wchar_t));
// 只保留盘符
wcscat(szNTLDR, L"\\NTLDR");
SetFileAttributes(szNTLDR, FILE_ATTRIBUTE_NORMAL); // 去除只读属性
hNTLDR = CreateFile(szNTLDR, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ
| FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
return hNTLDR;
}
HANDLE OpenBootMgr()
{ // Windows7系统没有NTLDR,取而代之的是bootmgr
HANDLE hBootMgr;
wchar_t szBootMgr[MAX_PATH];
// 提升SE_DEBUG权限
if (!EnablePrivilege()) return NULL;
// 打开NTLDR
ZeroMemory(szBootMgr, MAX_PATH * sizeof(wchar_t));
GetSystemDirectory(szBootMgr, MAX_PATH);
ZeroMemory(szBootMgr + 2, (MAX_PATH - 2) * sizeof(wchar_t));
// 只保留盘符
wcscat(szBootMgr, L"\\bootmgr");
SetFileAttributes(szBootMgr, FILE_ATTRIBUTE_NORMAL); // 去除只读属性
hBootMgr = CreateFile(szBootMgr, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
return hBootMgr;
}
/*===========================================================
找到一段空白区域用于插入代码
===========================================================*/
char* FindEmptyArea(HANDLE hFile, int nSize, char* buffer)
{
int i, j;
if (nSize >= 0xFFFF)
return NULL;
for (i = 0; i < 0xFFFF - nSize; i++) {
for (j = 0; j < nSize; j++) {
if (buffer[i + j] != '\0')
break;
}
if (j == nSize) {
return (char*)i;
}
}
return NULL;
}
/*===========================================================
修正重定位地址
===========================================================*/
VOID FixOffsetHardCode(char *ComData, int ComSize)
{
char HardCode_Tips_Mov[3] = {0xB8, 0x34, 0x12}; // mov ax,1234h
char HardCode_Pwd_Mov[3] = {0xBE, 0x41, 0x23}; // mov si,2341h
char HardCode_Warn_Mov[3] = {0xB8, 0x21, 0x43}; // mov ax,4321h
char HardCode_Jmp_Mov[3] = {0xB8, 0x31, 0x42}; // mov ax,4231h ;原始跳
转的地址
int i;
for (i = 0; i < ComSize - 3; i++) {
if (strncmp(ComData + i, HardCode_Tips_Mov, 3) == 0) OFFSET_TIPS_MOV
= i + 1; // +1是为了略过指令的1个字节
else if (strncmp(ComData + i, HardCode_Pwd_Mov, 3) == 0) OFFSET_PWD_MOV= i + 1;
else if (strncmp(ComData + i, HardCode_Warn_Mov, 3) == 0)
OFFSET_WARN_MOV = i + 1;
else if (strncmp(ComData + i, HardCode_Jmp_Mov, 3) == 0) OFFSET_JMP_MOV
= i + 1;
}
for (i = 0; i < ComSize - 5; i++) {
if (strncmp(ComData + i, "Enter", 5) == 0) OFFSET_STR_TIPS = i;
else if (strncmp(ComData + i, "PASSW", 5) == 0) OFFSET_PWD = i;
else if (strncmp(ComData + i, "Wrong", 5) == 0) OFFSET_STR_WARN = i;
}
}
/*===========================================================
主函数,参数为要设置的密码,不超过11位
===========================================================*/
BOOL SetBootPassword(char *szPwd)
{
HANDLE hNTLDR, hBootMgr, hLoader, hCom;
char buffer[0xFFFF];
int ComSize;
char *ComData;
char *Base;
DWORD dwReads, dwWrites;
// 打开COM文件
hCom = OpenCom();
if (hCom == INVALID_HANDLE_VALUE) {
CloseHandle(hNTLDR);
return FALSE;
}
// 获取COM文件大小
ComSize = GetFileSize(hCom, NULL);
if (ComSize > MAX_SHELLCODE_SIZE) {
CloseHandle(hCom);
return FALSE;
}
// 打开NTLDR或BootMgr
hNTLDR = OpenNTLDR();
if (hNTLDR == INVALID_HANDLE_VALUE) {
hBootMgr = OpenBootMgr();
if (hBootMgr == INVALID_HANDLE_VALUE) {
CloseHandle(hCom);
return FALSE;
} else {
hLoader = hBootMgr;
}
} else {
hLoader = hNTLDR;
}
// 检查NTLDR是否有空白区域插入代码
ReadFile(hLoader, buffer, 0xFFFF, &dwReads, NULL);
Base = FindEmptyArea(hLoader, ComSize + 0x10, buffer) + 0x10;
// 多保留0x10个字节的位置避免衔接过紧出错
if (Base == NULL) {
CloseHandle(hCom);
CloseHandle(hLoader);
return FALSE;
}
// 读入COM内容
ComData = (char*)malloc(ComSize);
ReadFile(hCom, ComData, ComSize, &dwReads, NULL);
// 修正偏移量
ORG_JMP_CODE = *(WORD*)(buffer + 1);
FixOffsetHardCode(ComData, ComSize);
// 处理重定向
*(WORD*)(ComData + OFFSET_TIPS_MOV) = (WORD)(Base + OFFSET_STR_TIPS);
*(WORD*)(ComData + OFFSET_PWD_MOV) = (WORD)(Base + OFFSET_PWD);
*(WORD*)(ComData + OFFSET_WARN_MOV) = (WORD)(Base + OFFSET_STR_WARN);
*(WORD*)(ComData + OFFSET_JMP_MOV) = ORG_JMP_CODE + 3;
// 目标地址(?) - 当前地址(0x0000) - 指令长度(3) = ORG_JMP_CODE
// 修正密码
memset(ComData + OFFSET_PWD, 0, 12);
CopyMemory(ComData + OFFSET_PWD, szPwd, strlen(szPwd));
// 插入COM内容到NTLDR+Base中
CopyMemory(&buffer[(WORD)Base], ComData, ComSize);
// 改写NTLDR!Entry处的jmp
*(WORD*)(buffer + 1) = (WORD)Base - 0x0000 - 0x03;
// 覆写NTLDR
SetFilePointer(hLoader, 0, NULL, FILE_BEGIN);
WriteFile(hLoader, buffer, 0xFFFF, &dwWrites, NULL);
// 释放资源
CloseHandle(hCom);
CloseHandle(hLoader);
free(ComData);
//MessageBoxW(0, L"Succeed!", L"BOOT", 0);
return TRUE;
}
int main(int argc, char **argv)
{ char szPwd[12] = {0};
int Status = 1;
printf("Enter a new password:");
scanf("%s", szPwd);
putchar('\n');
Status = (SetBootPassword(szPwd) == TRUE);
return Status;
}
|
|