首页 -> 安全研究
安全研究
绿盟月刊
绿盟安全月刊->第53期->安全文摘
作者:coolq
出处:http://www.linuxforum.net/forum/showflat.php?Cat=&Board=security&Number=
日期:2004-11-05
coolq
最近看了Secure Programming
Cookbook的12.2,感觉里边的构思很好,照葫芦画瓢,做了点修改。
平常的时候用strcmp比较字符串很容易被破解,而下例的主要方法是:
1. 先计算出需要比较字符串的散列值,CRC32、MD5、SHA1都可以,例子中用的是MD5
2.
对得到的散列值,一次取四位,构造一个指针数组,大小为16,其中只有一个指针是正确的,以该
四位值作为索引,得到一个指针,调用该指针的函数。正确的指针指向下一个函数,依此类推。
3. 最后四位对应的指针为出口函数,在这里为digest_ok
这样做的好处:
密码可以在代码中不出现名文而只是散列值;没有比较指令,破解的难度较大
注意:
该程序的使用需要openssl库的支持,当然你也可以把有用代码提取出来
-------------------------------------------------------------------------------------
/* Name: secure_str_compare.c
* Author: CoolQ
* Compile:
* 1) edit secure_str_compare.c
* set TEST_STRING to proper value
* 2) gcc -o generate secure_str_compare.c -lssl
* 3) ./generate > compare.c
* 4) edit compare.c
* in func main, point p to whatever you want to compare
* in func digest_ok, you can add some greetings or
* just leave it empty
* 5) gcc -o compare compare.c -lssl
* 6) ./compare
* if the string matches, you'll see "verify ok"
* .or.
* you get a segmentation fault
* Note:
* You must have openssl and openssl-devel installed
* If you want to use CRC32 or SHA1, only change DIGEST_LENGTH to 4 / 20,
* chage get_md5 to proper func
*/
#include <stdio.h>
#include <openssl/md5.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define TEST_STRING "1234567890"
#define DIGEST_LENGTH 16
/* print separator */
#define PRINT_SEP(i) if(((i+1) % 4) == 0) fprintf(stdout, "\n\t")
/* get md5 digest and put in result[DIGEST_LENGTH] */
void get_md5(unsigned char result[DIGEST_LENGTH])
{
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, TEST_STRING, strlen(TEST_STRING));
MD5_Final(result, &ctx);
return;
}
/* generate include file and function declaration */
void generate_fun_declare(void)
{
int count;
fprintf(stdout, "#include <openssl/md5.h>\n");
fprintf(stdout, "#include <stdio.h>\n");
fprintf(stdout, "#include <string.h>\n\n");
fprintf(stdout, "#define DIGEST_LENGTH %d\n\n", DIGEST_LENGTH);
fprintf(stdout, "static void calc_md5(const char *, unsigned charresult[DIGEST_LENGTH]);\n");
fprintf(stdout, "typedef void (*digest_check_fn)(unsigned char *);\n\n");
for(count = 0; count < DIGEST_LENGTH; count++){
fprintf(stdout, "static void digest_nib%d(unsigned char *digest);\n",
count * 2 + 1);
fprintf(stdout, "static void digest_nib%d(unsigned char *digest);\n",
count * 2 + 2);
}
fprintf(stdout, "\nstatic void digest_ok(void);\n");
return;
}
/* generate jmp function arrays */
void generate_jmp_array(unsigned char result[DIGEST_LENGTH])
{
int count, pos;
unsigned int low, high;
char r;
srandom((int) time(NULL));
fprintf(stdout, "digest_check_fn ");
for(count = 0; count < DIGEST_LENGTH; count++){
low = result[count] & 0x0F;
high = result[count] >> 4;
fprintf(stdout, "b%d[DIGEST_LENGTH] = { \n\t", count * 2 + 1);
for(pos = 0; pos < low; pos++){
r = random() & 0xFF;
fprintf(stdout, "digest_nib%d+%d,\t",
count * 2 + 2, r);
PRINT_SEP(pos);
}
fprintf(stdout, "digest_nib%d,\t", count * 2 + 2);
PRINT_SEP(low);
for(pos = low + 1; pos < DIGEST_LENGTH; pos++){
r = random() & 0xFF;
fprintf(stdout, "digest_nib%d+%d,\t",
count * 2 + 2, r);
PRINT_SEP(pos);
}
fprintf(stdout, "},\n");
fprintf(stdout, "b%d[DIGEST_LENGTH] = { \n\t", count * 2 + 2);
for(pos = 0; pos < high; pos++){
r = random() & 0xFF;
if(count != DIGEST_LENGTH - 1)
fprintf(stdout, "digest_nib%d+%d,\t",
count * 2 + 3, r);
else
fprintf(stdout, "digest_ok+%d,\t", r);
PRINT_SEP(pos);
}
if(count != DIGEST_LENGTH - 1)
fprintf(stdout, "digest_nib%d,\t", count * 2 + 3);
else
fprintf(stdout, "digest_ok,\t");
PRINT_SEP(high);
for(pos = high + 1; pos < DIGEST_LENGTH; pos++){
r = random() & 0xFF;
if(count != DIGEST_LENGTH - 1)
fprintf(stdout, "digest_nib%d+%d,\t",
count * 2 + 3, r);
else
fprintf(stdout, "digest_ok+%d,\t", r);
PRINT_SEP(pos);
}
fprintf(stdout, "}%s", count == DIGEST_LENGTH - 1
? ";\n" : ",\n");
}
return;
}
/* generate DIG_TABLE_LOOKUP macro */
void generate_macro(void)
{
fprintf(stdout, "#define DIG_TABLE_LOOKUP(table, pdigest, low) \\\n");
fprintf(stdout, " do{ \\\n");
fprintf(stdout, " int index = *pdigest & 0x0F; \\\n");
fprintf(stdout, " digest_check_fn next = table[index]; \\\n");
fprintf(stdout, " *pdigest >>= 4; \\\n");
fprintf(stdout, " if(low == 1) pdigest++; \\\n");
fprintf(stdout, " (*next)(pdigest); \\\n");
fprintf(stdout, " }while(0) \n");
return;
}
/* generate function logic */
void generate_func_exec(void)
{
int count;
for(count = 0; count < DIGEST_LENGTH; count++){
fprintf(stdout, "static void digest_nib%d(unsigned char *digest)"
" \n{ DIG_TABLE_LOOKUP(b%d, (digest), 0); }\n",
count * 2 + 1, count * 2 + 1);
fprintf(stdout, "static void digest_nib%d(unsigned char *digest)"
" \n{ DIG_TABLE_LOOKUP(b%d, (digest), 1); }\n",
count * 2 + 2, count * 2 + 2);
}
fprintf(stdout, "\nstatic void calc_md5(const char *p, unsigned charresult[DIGEST_LENGTH])\n");
fprintf(stdout, "{\n");
fprintf(stdout, "\tMD5_CTX ctx;\n");
fprintf(stdout, "\tMD5_Init(&ctx);\n");
fprintf(stdout, "\tMD5_Update(&ctx, p, strlen(p));\n");
fprintf(stdout, "\tMD5_Final(result, &ctx);\n");
fprintf(stdout, "\n\treturn;\n}\n");
fprintf(stdout, "static void digest_ok(void)"
" { printf(\"Verify OK.\\n\");} \n");
return;
}
/* show you how to use */
void generate_func_use(void)
{
fprintf(stdout, "int main(int argc, char *argv[])\n");
fprintf(stdout, "{\n");
fprintf(stdout, "\tunsigned char md5sum[DIGEST_LENGTH];\n");
fprintf(stdout, "\tunsigned char *p = \"1234567890\";\n\n");
fprintf(stdout, "\tcalc_md5(p, md5sum);\n");
fprintf(stdout, "\tdigest_nib1(md5sum);\n");
fprintf(stdout, "\treturn 0;\n}\n");
return;
}
/* main func */
int main(int argc, char *argv[])
{
unsigned char md5sum[DIGEST_LENGTH];
int count;
get_md5(md5sum);
generate_fun_declare();
generate_jmp_array(md5sum);
generate_macro();
generate_func_exec();
generate_func_use();
return 0;
}
版权所有,未经许可,不得转载