NTLM的PROXY穿越

以前在sina的坑里面对NTLM技术和实现的方式进行了分析,并给出了代码。记得最凄惨的是找DES算法,N个地方给出的计算值都不一样,郁闷了很久。现在逐步将这些blog移到CSDN上。

Base64的算法,是通过网上共产主义获取,MD4,MD5,HMAC MD5的算法是RFC中提供的,其余的可以根据上面的步骤进行编写。我提供一个源代码的例子。其中arith_开头的相关算法,httppc_ntlm是NTLM的type1、type2、type3消息的应答构成,test_httppc_connect是一个测试的例子,里面没有main函数,但是另外构造一个main函数,在wei_set_proxy_info之后,调用wei_httppc_connect就可以了。可在http://download.csdn.net/source/1113570 下载。

不好意思,收到留言,说少了头文件,我看了一下,少了md.h头文件,不从在下面:

 

/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
   License to copy and use this software is gra/* Copyright (C) 1991-2,
   RSA Data Security, Inc. Created 1991. All rights reserved.
   License to copy and use this software is granted provided that it
   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
   Algorithm" in all material mentioning or referencing this software
   or this function.

   License is also granted to make and use derivative works provided
   that such works are identified as "derived from the RSA Data
   Security, Inc. MD4 Message-Digest Algorithm" in all material
   mentioning or referencing the derived work.

   RSA Data Security, Inc. makes no representations concerning either
   the merchantability of this software or the suitability of this
   software for any particular purpose. It is provided "as is"
   without express or implied warranty of any kind.

   These notices must be retained in any copies of any part of this
   documentation and/or software.
*/

#ifdef __cplusplus
extern "C" {
#endif

#ifndef WEI_MD_H
#define WEI_MD_H
#ifndef IN
#define IN
#endif

#ifndef OUT
#define OUT
#endif

/************************************ 算法:MD4和MD5 *********************************/
//从RFC1320 The MD4 Message-Digest Algorithm的附录
//从RFC1321 The MD5 Message-Digest Algorithm的附录
/* PROTOTYPES should be set to one if and only if the compiler supports function
 * argument prototyping.The following makes PROTOTYPES default to 0 if it has not
 * already been defined with C compiler flags.
 */
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif

/* POINTER defines a generic pointer type */
typedef unsigned char * POINTER;

/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;

/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;

/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.If using PROTOTYPES,
 * then PROTO_LIST returns the list, otherwise it returns an empty list.
 */

#if PROTOTYPES
#define PROTO_LIST(list) list
#else

#define PROTO_LIST(list) ()
#endif

/* MD4 context. */
typedef struct {
  UINT4 state[4];                                   /* state (ABCD) */
  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
  unsigned char buffer[64];                         /* input buffer */
} MD4_CTX;

void MD4Init PROTO_LIST ((MD4_CTX *));
void MD4Update PROTO_LIST
  ((MD4_CTX *, unsigned char *, unsigned int));
void MD4Final PROTO_LIST ((unsigned char [16], MD4_CTX *));

/* MD5 context. */
typedef struct {
  UINT4 state[4];                                   /* state (ABCD) */
  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
  unsigned char buffer[64];                         /* input buffer */
} MD5_CTX;

void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
  ((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));

#endif

#ifdef __cplusplus
}
#endif

因为我没有认真地打包封装,而是从我的一个project中抽出了,有些遗漏,请大家原谅。今天又有网友来问PRIVATE在哪里定义。因为代码不在手头的机器上,没法仔细看,PRIVATE的定义如下
#define PRIVATE
定义为空,这是模仿C++的private,说明这个函数不会被其他文件引用,只用于本文件。

最近又收到网友的来信,说少了几个util文件。这个是不在ntlm的算法中,而是在验证例子test_httppc_connect.cpp中使用。查了一下,我确实没有放到网上。汗啊,因为验证例子是从某个程序中抽取出来,里面包含一个很简单的http的解析。我本来想update资源,没有找到update的方法。所以只好在这里补充。需要说明的是这部分和真正的算法没有直接关系。
这是头文件 

#ifdef __cplusplus
extern "C" {
#endif
#ifndef WEI_UTIL_H
#define WEI_UTIL_H
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef PRIVATE
#define PRIVATE
#endif
/****************************** 字符串处理 *********************************/
/** 检索某个字符串出现的次数 */
int wei_util_get_str_num(IN char * buf,IN char * ch);
/** 本函数,字符串B的长度必须小于字符串A的长度。或者保证str的足够空间。*/
bool wei_util_replace_all(IN OUT char * str,IN const char * a, IN const char * b);
/** 本函数将影响到原始出入的buf,提请特别注意,可以使用副本来处理。类似JAVA的split */
bool wei_util_split(IN OUT char * buf,IN char * ch, IN int num ,OUT char * * dst);
/** 检查是否都是数字*/
bool wei_util_check_allnum(IN char * a);
/** 去除字符串的前后空格 */
void wei_util_str_trim(IN OUT char * a);
/** 字符串之间的比较,可选择是否大小写敏感,以及设定比较的长度,如果为长度<=0,表示全字符串比较。*/
bool wei_util_str_compare(IN const char * a, IN const char * b,IN bool isCase,IN int length);
/** a忽略前后空格和b进行比较*/
bool wei_util_str_compare_trim(char * a, char * b,bool is_case);
#endif
#ifdef __cplusplus
}
#endif

这是源代码文件

// wei_util.cpp: implementation of the UTIL FUNTIONS.
//
//
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util/wei_util.h"

/********************************* PART 1: 字符串处理 ********************************/
/** 检索某个字符串出现的次数 */        
int wei_util_get_str_num(IN char * buf,IN char * ch){
    int num = 0;
    char * a = buf, * b = NULL;
    while((b = strstr(a,ch)) != NULL){
      num ++;
    a = b + strlen(ch);
  }
  return num;
}

/** 本函数,字符串B的长度必须小于字符串A的长度。或者保证str的足够空间。*/


bool wei_util_replace_all(IN OUT char * str,IN const char * a,IN const char * b)
{
  char * c;
  int offset = strlen(a) - strlen(b);
  if(offset < 0)
    return false;

  while( (c= strstr(str,a)) != NULL){
    sprintf(c,"%s%s",b,c+strlen(a));
  }
  return true;  
}

/*
void tempPrint(char * buf){
  LOG(LOG_DEBUG,"========二进制输出 长度:%d",strlen(buf));
  for(int i = 0 ; i < strlen(buf)/8 + 1 ; i ++){
    LOG(LOG_DEBUG,"%d/t%02x %02x %02x %02x %02x %02x %02x %02x",i*8,
      (unsigned char)buf[8*i],(unsigned char)buf[8*i+1],(unsigned char)buf[8*i+2],
      (unsigned char)buf[8*i+3],(unsigned char)buf[8*i+4],(unsigned char)buf[8*i+5],
      (unsigned char)buf[8*i+6],(unsigned char)buf[8*i+7]);
  }

}*/
                           
/** 本函数将影响到原始出入的buf,提请特别注意,可以使用副本来处理。*/  
bool wei_util_split(IN OUT char * buf,IN char * ch, IN int num ,OUT char * * dst){
  char * a = buf, * b = buf;
  for(int i = 0 ; i < num ; i ++){
    b = strstr(a,ch);
    if(i == num -1){
      dst[i] = a;
    }else if(b == NULL){
      return false;
    }else{
      dst[i] = a;
      a = b + strlen(ch);
      b[0] = 0;
    }
  }
  return true;
}


/** 检查是否都是数字*/                    
bool wei_util_check_allnum(char * a){
  if(a == NULL || strlen(a) == 0)
    return false;

  for(unsigned int i = 0 ; i< strlen(a);i ++){
    if(a[i] < '0' || a[i] > '9')
      return false;
  }
  return true;
}

/** 去除字符串的前后空格 */
void wei_util_str_trim(IN OUT char * a){
  char * temp = NULL,* p = NULL, * e = NULL;

  if(a == NULL || strlen(a) == 0)
    return;
  temp = (char * ) malloc(strlen(a) + 1);
  memset(temp,0,sizeof(temp));

  p = a;
  while(p[0] == ' '){
    p ++;
  }
  e = a + strlen(a) -1;
  while( * e == ' ' ){
    e --;
  }

  memcpy(temp,p,strlen(p) - strlen(e) + 1);
  strcpy(a,p);
  free(temp);
}


/** 字符串之间的比较,可选择是否大小写敏感,以及设定比较的长度,如果为长度<=0,表示全字符串比较。*/
bool wei_util_str_compare(IN const char * a, IN const char * b,IN bool isCase,IN int length){
#ifdef _LINUX
  if(isCase)
    return length <= 0 ? strcmp(a,b) == 0 : strncmp(a,b,n) == 0;
  else
    return length <= 0 ? strcasecmp(a,b) == 0: strncasecmp(a,b,n) == 0;
#endif

  if(isCase)
    return length <= 0 ? strcmp(a,b) == 0 : strncmp(a,b,length) == 0;

  int len_a = strlen(a);
  int len_b = strlen(b);
  if(length <= 0 && len_a != len_b)
    return false;
  else if(length >0 && (len_a < length || len_b < length))
    return false;
  if(length <= 0)
    length = len_a;

  int step = 'a' - 'A';

  for(int i = 0 ; i < length ; i ++){
    if(a[i] != b[i]){
      if(a[i] - b[i] == step && a[i] >= 'a' && a[i] <= 'z')
        continue;
      if(b[i] - a[i] == step && a[i] >= 'A' && a[i] <= 'Z')
        continue;
      return false;
    }
  }
  return true;
}


/** a忽略前后空格和b进行比较*/
bool wei_util_str_compare_trim(char * a, char * b,bool is_case){
  char * h = a;
  char * e = a + strlen(a) -1;

  while ( * h == ' ')
    h ++;

  while ( * e == ' ')
    e --;

  if(strlen(b) != (unsigned int )(e - h) +1)
    return false;

  if(is_case)
    return strncmp(h,b,strlen(b)) == 0;

  int step = 'a' - 'A';

  for(unsigned int i = 0 ; i < strlen(b) ; i ++){
    if(h[i] != b[i]){
      if(h[i] - b[i] == step && h[i] >= 'a' && h[i] <= 'z')
        continue;
      if(b[i] - h[i] == step && h[i] >= 'A' && h[i] <= 'Z')
        continue;
      return false;
    }
  }

  return true;
}
//*********** end of PART 1 : 字符串处理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
HTTP PROXYNTLM的客户端的C源代码。包含相关的DES等算法在内。Base64的算法,是通过网上共产主义获取,MD4,MD5,HMAC MD5的算法是RFC中提供的,其余的可以根据下面链接的步骤进行编写。我提供一个源代码的例子。其中arith_开头的相关算法,httppc_ntlmNTLM的type1、type2、type3消息的应答构成,test_httppc_connect是一个测试的例子,里面没有main函数,但是另外构造一个main函数,在wei_set_proxy_info之后,调用wei_httppc_connect就可以了。详细见http://blog.csdn.net/flowingflying/archive/2009/03/03/3952796.aspx 有朋友说少了头文件,我查了一下,不好意思,少了md.h。请参考下面。 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD4 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #ifdef __cplusplus extern "C" { #endif #ifndef WEI_MD_H #define WEI_MD_H #ifndef IN #define IN #endif #ifndef OUT #define OUT #endif /************************************ 算法:MD4和MD5 *********************************/ //从RFC1320 The MD4 Message-Digest Algorithm的附录 //从RFC1321 The MD5 Message-Digest Algorithm的附录 /* PROTOTYPES should be set to one if and only if the compiler supports function * argument prototyping.The following makes PROTOTYPES default to 0 if it has not * already been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char * POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ typedef unsigned long int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.If using PROTOTYPES, * then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif /* MD4 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD4_CTX; void MD4Init PROTO_LIST ((MD4_CTX *)); void MD4Update PROTO_LIST ((MD4_CTX *, unsigned char *, unsigned int)); void MD4Final PROTO_LIST ((unsigned char [16], MD4_CTX *)); /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); #endif #ifdef __cplusplus } #endif 因为我没有认真地打包封装,而是从我的一个project中抽出了,有些遗漏,请大家原谅。今天又有网友来问PRIVATE在哪里定义。因为代码不在手头的机器上,没法仔细看,PRIVATE的定义如下 #define PRIVATE 定义为空,这是模仿C++的private,说明这个函数不会被其他文件引用,只用于本文件。 最近又收到网友的来信,说少了几个util文件。这个是不在ntlm算法中,而是在验证例子test_httppc_connect.cpp中使用。查了一下,我确实没有放到网上。汗啊,因为验证例子是从某个程序中抽取出来,里面包含一个很简单的http的解析。我本来想update资源,没有找到 update的方法。需要说明的是这部分和真正的算法没有直接关系。放在这里,太长了,如果需要的网友,请到http://blog.csdn.net/flowingflying/archive/2009/03/03/3952796.aspx 那里下载。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值