簡體   English   中英

使用shell_exec()從PHP腳本調用C程序

[英]Calling C program from a PHP script using shell_exec()

我是Web開發的新手,目前,在構建“登錄”頁面時陷入困境。

我寫了一個PHP腳本,當輸入時會獲取用戶名和密碼。 然后將密碼作為參數發送到我編寫的C程序中,該程序只是對密碼(MD5)進行哈希處理。 使用以下代碼完成此操作:

$username = $_POST['uname'];
$password = $_POST['passwd'];

$hashvalue = shell_exec("md5.exe $password");

現在,當我在登錄表單中輸入密碼為1234時 ,得到的輸出為f7d4cef3bfacebfc49d5574e7d9c1d6f

但是當我分別運行C程序時使用1234作為輸入時,會得到不同的輸出81dc9bdb52d04dc20036dbd8313ed055 這也是我實際上應該得到的輸出。 當我檢查了各種在線MD5哈希程序后,它們給出了相同的輸出。

在C程序中,我使用gets()獲取輸入,並使用printf顯示輸出。 另外,我使用了MySQL數據庫(phpMyAdmin)。

C程序代碼:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

typedef union uwb {
    unsigned w;
    unsigned char b[4];
} MD5union;

typedef unsigned DigestArray[4];

unsigned func0( unsigned abcd[] ){
    return ( abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]);}

unsigned func1( unsigned abcd[] ){
    return ( abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]);}

unsigned func2( unsigned abcd[] ){
    return  abcd[1] ^ abcd[2] ^ abcd[3];}

unsigned func3( unsigned abcd[] ){
    return abcd[2] ^ (abcd[1] |~ abcd[3]);}

typedef unsigned (*DgstFctn)(unsigned a[]);



unsigned *calctable( unsigned *k)
{
    double s, pwr;
    int i;

    pwr = pow( 2, 32);
    for (i=0; i<64; i++) {
        s = fabs(sin(1+i));
        k[i] = (unsigned)( s * pwr );
    }
    return k;
}


unsigned rol( unsigned r, short N )
{
    unsigned  mask1 = (1<<N) -1;
    return ((r>>(32-N)) & mask1) | ((r<<N) & ~mask1);
}

unsigned *md5( const char *msg, int mlen)
{
    /*Initialize Digest Array as A , B, C, D */
    static DigestArray h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
    static DgstFctn ff[] = { &func0, &func1, &func2, &func3 };
    static short M[] = { 1, 5, 3, 7 };
    static short O[] = { 0, 1, 5, 0 };
    static short rot0[] = { 7,12,17,22};
    static short rot1[] = { 5, 9,14,20};
    static short rot2[] = { 4,11,16,23};
    static short rot3[] = { 6,10,15,21};
    static short *rots[] = {rot0, rot1, rot2, rot3 };
    static unsigned kspace[64];
    static unsigned *k;

    static DigestArray h;
    DigestArray abcd;
    DgstFctn fctn;
    short m, o, g;
    unsigned f;
    short *rotn;
    union {
        unsigned w[16];
        char     b[64];
    }mm;
    int os = 0;
    int grp, grps, q, p;
    unsigned char *msg2;

    if (k==NULL) k= calctable(kspace);

    for (q=0; q<4; q++) h[q] = h0[q];   // initialize

    {
        grps  = 1 + (mlen+8)/64;
        msg2 = malloc( 64*grps);
        memcpy( msg2, msg, mlen);
        msg2[mlen] = (unsigned char)0x80;
        q = mlen + 1;
        while (q < 64*grps){ msg2[q] = 0; q++ ; }
        {
            MD5union u;
            u.w = 8*mlen;
            q -= 8;
            memcpy(msg2+q, &u.w, 4 );
        }
    }

    for (grp=0; grp<grps; grp++)
    {
        memcpy( mm.b, msg2+os, 64);
        for(q=0;q<4;q++) abcd[q] = h[q];
        for (p = 0; p<4; p++) {
            fctn = ff[p];
            rotn = rots[p];
            m = M[p]; o= O[p];
            for (q=0; q<16; q++) {
                g = (m*q + o) % 16;
                f = abcd[1] + rol( abcd[0]+ fctn(abcd) + k[q+16*p] + mm.w[g], rotn[q%4]);

                abcd[0] = abcd[3];
                abcd[3] = abcd[2];
                abcd[2] = abcd[1];
                abcd[1] = f;
            }
        }
        for (p=0; p<4; p++)
            h[p] += abcd[p];
        os += 64;
    }
    return h;
}

int main( int argc, char *argv[] )
{
    int j,k;
    char msg[500];
    gets(msg);
    unsigned *d = md5(msg, strlen(msg));
    MD5union u;
    for (j=0;j<4; j++){
        u.w = d[j];
        for (k=0;k<4;k++) 
            printf("%02x",u.b[k]);
    }
    return 0;
}

我究竟做錯了什么?

我已經讀過許多內置函數,例如bcrypt,scrypt等。但這只是出於練習目的,因此想使用自己的代碼。

謝謝

在您的C程序中,假設它是MD5,則正確地對輸入字符串進行了哈希處理,那么實際上可能沒問題。

這個問題可能根本不是問題,在這兩個過程中,您的MD5哈希值都是正確的。 (即使它們看起來完全不同,它們也可以' 保持 '相同的值'1234' )只是堆棧的內容在一個實例與另一個實例之間是不同的,並且null之后的某些字符串來自堆棧。

發生的情況是,在一個實例中,C函數正在對該字符串'1234__________________'哈希'1234__________________' (其中_是null或\\ 0 char

而另一個實例正在對該字符串'1234_some_random_values'哈希'1234_some_random_values'

兩個字符串都包含1234一個null字符,但是在空后的字符是不同的。

嘗試用所有空值預填充您的臨時字符串,然后在密碼之間進行復制,以確保在MD5對其進行哈希處理之前,確保字符串緩沖區的其余部分為“空”。

(如果您想驗證我是正確的,則可以通過unMD5散列來確認。在Wikipedia上,您可以看到散列算法接受數據的“塊”,而不關心NULL字符在哪里:

MD5將可變長度消息處理為128位固定長度輸出。 輸入消息分為512位塊(十六個32位字)的塊; 填充該消息,以便其長度可被512整除。

從這里https://en.wikipedia.org/wiki/MD5也是從這個解釋開始,如果您的密碼長度恰好是16個32位字(16個32位字)乘以16 = 64個字符,那么MD5哈希應該相同空字符后面的字符數組中的內容,因為該算法將不會在64個字符的邊界之后查找更多字符。

嘗試添加

memset(msg,0,500); 

在你gets之前。

(我不考慮所有安全問題:)

我認為這可能對您做兩件事很重要

  1. 開始考慮設計的安全性
  2. 熟悉PHP標准庫,特別是

    http://php.net/manual/zh/function.md5.php
    http://php.net/manual/zh/function.filter-input.php

我首先列出了安全性,因為,正如其他人指出的那樣,您不應該直接訪問GET或POST。 由於您只是在練習,因此在編程時始終要牢記安全性,不要重蹈覆轍,祝您好運。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM