Access 密碼破解原理- -


Access 密碼破解原理- -

                                      

 

         ACCESS數據庫的密碼極容易被破,使用網上流行的工具,不管你的密碼多少位很快就能被破出來。原以為ACCESS與WORD EXCEL一樣,作為MS OFFICE的套件,一樣采用DES加密,非破暴力破解不可。密碼倍數越長越難破。結果,一試,果然很快被破出來。
    經查詢,原來ACCESS加密過於簡單。如下:
    在庫文件的地址00000042處開始的40個字節是Access 2000庫的密碼位。如果一個未加密的庫,這40個字節原始數據依次為:29 77 EC 37 F2 C8 9C FA 69 D2 28 E6 BC 3A 8A 60 FB 18 7B 36 5A FE DF B1 D8 78 13 43 60 23 B1 33 9B ED 79 5B 3D 33 3D 39 7C 2A 。當你給數據庫設置了密碼后,這40個字節就變成了密鑰。因此,要破解密碼而不需保持原庫的密碼,只要將00000042 處開始的40個字節還原成原始數據就行了,從而跳過口令。
另外,當你設置了密碼后,Access 2000 就將你的密碼的ASCII碼與以上的40個字節數據進行異或操作,因此,從庫文件的地址00000042開始的40個字節就變成了密鑰了。例如,如果你設置的密碼為12345678901234567890(注意:最多只能設20個ASCII字符),經過異或操作后,則從00000042處開始的40個字節的數據就變成了 18 77 DE 37 C1 C8 A8 FA 5C D2 1E E6 8B 3A B2 60 C2 18 4B 36 6B FE ED B1 EB 78 27 43 55 23 87 33 AC ED 41 5B 04 39 4C 2A 。大家都知道,一個數據經過一次異或操作后,再一次經過同樣的異或操作就可還原了。因此,對已經設置了密碼的Access 2000庫,只要將40個密鑰數據與原始的40個數據進行一次異或操作就可得到密碼了。
    最后,要注意的是,由於ACCESS 2000對每個密碼字符采用雙字節表示,故40個字節原始數據可依次分為20組,每組代表一個密碼字符,進行異或操作的是每組的第一個字節,第二個字節不變。
// CrackAccessPassDlg.cpp : 實現文件
//

#include "stdafx.h"
#include "CrackAccessPass.h"
#include "CrackAccessPassDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用於應用程序“關於”菜單項的 CAboutDlg 對話框

class CAboutDlg : public CDialog
{
public:
    CAboutDlg();

// 對話框數據
    enum { IDD = IDD_ABOUTBOX };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 實現
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CCrackAccessPassDlg 對話框




CCrackAccessPassDlg::CCrackAccessPassDlg(CWnd* pParent /**//*=NULL*/)
    : CDialog(CCrackAccessPassDlg::IDD, pParent)
    , m_filePath(_T(""))
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCrackAccessPassDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT1, m_filePath);
}

BEGIN_MESSAGE_MAP(CCrackAccessPassDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_BN_CLICKED(IDC_BUTTON1, &CCrackAccessPassDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// CCrackAccessPassDlg 消息處理程序

BOOL CCrackAccessPassDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 將“關於”菜單項添加到系統菜單中。

    // IDM_ABOUTBOX 必須在系統命令范圍內。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 設置此對話框的圖標。當應用程序主窗口不是對話框時,框架將自動
    //  執行此操作
    SetIcon(m_hIcon, TRUE);            // 設置大圖標
    SetIcon(m_hIcon, FALSE);        // 設置小圖標

    // TODO: 在此添加額外的初始化代碼

    return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
}

void CCrackAccessPassDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialog::OnSysCommand(nID, lParam);
    }
}

// 如果向對話框添加最小化按鈕,則需要下面的代碼
//  來繪制該圖標。對於使用文檔/視圖模型的 MFC 應用程序,
//  這將由框架自動完成。

void CCrackAccessPassDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用於繪制的設備上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使圖標在工作矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 繪制圖標
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

//當用戶拖動最小化窗口時系統調用此函數取得光標顯示。
//
HCURSOR CCrackAccessPassDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}


void CCrackAccessPassDlg::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知處理程序代碼
    CFileDialog fd(TRUE,"*.mdb","",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"ACCESS數據庫文件(*.mdb)|*.mdb|所有文件(*.*)|*.*||",NULL,0);
    INT_PTR nResponse = fd.DoModal();
    if(nResponse == IDOK)
    {
        m_filePath = fd.GetPathName();
        UpdateData(false);
        DoCrack();
    }
}

/**//*
* @ 解密工作
*/
void CCrackAccessPassDlg::DoCrack()
{
    CString PassWord;
    BYTE accVer[3] = {0};
    BYTE accID = 0x00;
    BYTE accFile[40] = {0};
    BYTE accDataKey[128] = {0};

    char accFlagString[16] = {0};

    //以只讀方式打開
    CFile myFile(m_filePath,CFile::modeRead | CFile::shareDenyNone);
    DWORD len = myFile.GetLength();
    if(len > 320)
    {
        myFile.Seek(66,CFile::begin);
        myFile.Read(&accFile,sizeof(accFile));

        myFile.Seek(156,CFile::begin);
        myFile.Read(&accVer,sizeof(accVer));

        myFile.Seek(20,CFile::begin);
        myFile.Read(&accID,sizeof(accID));

        myFile.Seek(24,CFile::begin);
        myFile.Read(&accDataKey,sizeof(accDataKey));

        myFile.Seek(4,CFile::begin);
        myFile.Read(&accFlagString,sizeof(accFlagString));
    }
    myFile.Close();

    if(strcmp(accFlagString,"Standard Jet DB"))
    {
        SetDlgItemText(IDC_VER,"不是Access數據庫!");
        return;
    }

    char *sKey2K = "3074EC37EBCB9CFA70D128E6A5398A60E21B7B3643FDDFB1C17B13437920B13382EE795B243A7C2A";
    char *sKey97 = "86FBEC375D449CFAC65E28E613";

    CString Version;
    //判斷版本雖然沒用,先留着
    if(accVer[0] == '0')
    {
        Version = "3.51";
    }
    else
    {
        Version = (CString)accVer;
    }

    Version = (accID == 0 ? "Access 97":"Access 2000");
    SetDlgItemText(IDC_VER,Version);

    //取密碼
    if(accID == 1)
    {
        PassWord = CrackPassDirect(accDataKey);
        if ( PassWord.GetLength() == 0)
        {
            PassWord = "沒有密碼";
        }
    }
    else if(accID == 0)
    {
        PassWord = CrackPass97(accFile);
        if(PassWord.GetLength() ==0)
        {
            PassWord = "沒有密碼";
        }
    }
    else
    {
        PassWord = "不是Access數據庫";
    }
    SetDlgItemText(IDC_PASS,PassWord);
}

CString CCrackAccessPassDlg::CrackPassDirect(BYTE (&f_bytes)[128])
{
    CString ret;
    long l;
    BYTE EncryptKey[4];       //初始密鑰
    BYTE EncryptRet[258] = {0};

    EncryptKey[0] = 0xC7;
    EncryptKey[1] = 0xDA;
    EncryptKey[2] = 0x39;
    EncryptKey[3] = 0x6b;

    //得到解密Key
    for(l=0;l<=255;l++)
    {
        EncryptRet[l] = l;
    }
    long temp1,temp2,temp3,temp4,temp5,temp6,temp7,temp8;
    temp1 = temp2 = temp3 = temp4 = temp5 = temp6 = temp7 = temp8 = 0;
    for(l=0;l<=255;l++)
    {
        temp1 = temp2;
        temp1 = EncryptKey[temp1];
        temp4 = EncryptRet[l];
        temp1 = temp1 + temp4;
        temp4 = temp3;
        temp1 = temp1 + temp4;
        temp1 = temp1 & 0x800000FF;
        temp3 = temp1;
        temp1 = EncryptRet[l];
        temp5 = temp1;
        temp1 = temp3;
        temp1 = EncryptRet[temp1];
        EncryptRet[l] = temp1;
        temp4 = temp3;
        EncryptRet[temp4] = temp5;
        temp1 = temp2;
        temp1++;
        temp4 = temp1 % 4;
        temp2 = temp4;
    }
    //運算結束

    //又一輪運算
    temp1=temp2=temp3=temp4=temp5=temp6=temp7=temp8=0;
    temp4 = EncryptRet[0x100];
    temp1 = EncryptRet[0x101];
    for(l=1;l<=0x80;l++)
    {
        temp4++;
        temp4 &= 0x800000FF;
        temp3 = temp4 & 0xff;
        temp5 = EncryptRet[temp3];
        temp1 &= 0xff;
        temp5 += temp1;
        temp1 = temp5 & 0x800000FF;
        temp6 = EncryptRet[temp4];
        temp5 = EncryptRet[temp1];
        EncryptRet[temp3] = temp5;
        temp2 = temp1;
        EncryptRet[temp2] = temp6;
        temp5 = EncryptRet[temp3];
        temp3 = EncryptRet[temp1 & 0xff];
        temp5 += temp3;
        temp5 &= 0x800000FF;
        temp7 = temp5;
        temp3 = temp8;
        temp5 = EncryptRet[temp5];
        long t = f_bytes[temp3] ^ temp5;
        f_bytes[temp3] = t;
        temp8 ++;
    }
    EncryptRet[0x100] = temp4;
    EncryptRet[0x101] = temp1;
    //又一輪結束
    double db;
    ::MoveMemory(&db,&f_bytes[90],8);
    //::RtlMoveMemory(&db,(&f_bytes[0])+90,8);
    long Key = (int)db;

    long lResult[20];
    for(l=0;l<20;l++)
    {
        lResult[l] = f_bytes[l*2+42]+256*(long)f_bytes[l*2+43];
        if(l%2 == 0)
        {
            lResult[l] ^= Key;
        }
        if(lResult[l] != 0)
        {
            ret += (char)lResult[l];
        }
    }
    return ret;
}

CString CCrackAccessPassDlg::CrackPass97(BYTE (&f_bytes)[40])
{
    CString ret;
    BYTE KEY[] = {0X86,0xfb,0xec,0x37,0x5d,0x44,0x9c,0xfa,0xc6,0x5e,0x28,0xe6,0x13};
    long lAsc;
    for(int i=0;i<sizeof(KEY);i++)
    {
        lAsc = f_bytes[i] ^ KEY[i];
        if(lAsc != 0)
        {
            ret += (char)lAsc;
        }
    }
    return ret;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM