Windows 10 x64 专业版 编译与测试【调试】Openssl【OpenSSL_1_0_2h】之 TLS

本人出于对 OpenSSL 的 TLS 协议的好奇,而走上了调试 OpenSSL 的道路。

在调试过程中也遇到过很多的坑,现在调试成功了,便记录下来,方便日后查看,

由于各种原因,我选择的 OpenSSL 的版本为: OpenSSL_1_0_2h

目录

0x01 下载 OpenSSL 源码

0x02 配置开发环境

0x03 编译 OpenSSL

0x04 编译带符号的 OpenSSL【Debug 版本】

0x05 输出结果对比

0x06 调试 OpenSSL 的源代码

0x07 调试 OpenSSL 的相关配置

0x08 使用 Wireshark 抓包分析 TLS 协议

 

0x01 下载 OpenSSL 源码

OpenSSL下载地址如下【也可以自己去 OpenSSL 的官网找】:

OpenSSL_1_0_2h:https://www.openssl.org/source/old/1.0.2/openssl-1.0.2h.tar.gz

OpenSSL官网: https://www.openssl.org/

下载好 OpenSSL 之后解压出来,我的解压路径是:

E:\OpenSSL\openssl-OpenSSL_1_0_2h\

解压出来就可以看到 OpenSSL 的目录结构了,如下图所示:

 

0x02 配置开发环境

下载好 OpenSSL 源码之后就可以开始进行编译了,由于我们是在 Windows 上编译,因此,与编译相关的信息可以查看源码根目录下的 【INSTALL】和【INSTALL.W32】文件,里面有关于编译命令的解释说明。但是,在编译之前,我们需要安装 Perl,于是去 Perl.org 【https://www.perl.org/get.html#win32】官网下载好Perl,并安装好。当然,VC6编译器也是需要有一个的,我使用的是VS2010,打开 VS2010 的命令提示符,如下图所示:

我们不使用 X64 版本的,因为我们要编译 32 位的 DLL。

注:


这里关于Win 10 上的 Perl 有个坑,我安装的Perl 是 5.16.2 版本,在命令行中输入:

> Perl test.pl 

的时候,不是执行 test.pl 这个脚本文件,而是直接进入Perl 交互模式,这就非常蛋疼了,因为在配置 OpenSSL 的时候用到这样的命令,如果这样没办法执行脚本,那就没办法配置 OpenSSL 了,于是我就直接在 Perl 安装的目录下【默认是 C:\Perl\】,把原来的 bin 文件夹中的 Perl.exe 删除掉,然后把 perl5.16.2.exe 复制一份,重命名为 Perl.exe 【也是在bin文件夹中】,如下图所示:

这才变成我们常用的模式,这样的话,在命令行中输入

> Perl test.pl 

就会是直接执行 test.pl 这个脚本了,而不是进入交互模式,如下图所示:

【如果你没有遇到这个问题,则可以忽略这个部分】


 

0x03 编译 OpenSSL

以上步骤都完成之后,我们就可以进行编译工作了,因为不同的 OpenSSL 版本的编译命令可能会不太一样,所以,如果你是用别的版本的 OpenSSL 的话,有可能要用别的命令来编译,现在我们使用的是: OpenSSL_1_0_2h 

默认编译的是 Release 版本,使用的命令如下:

【在VS2010 命令行中执行】

> Perl Configure VC-WIN32 no-asm --prefix=C:\MyProgramFiles\OpenSSLv1.0.2h --openssldir=C:\MyProgramFiles\OpenSSLv1.0.2h\SSL
> ms\do_ms
> nmake -f ms\ntdll.mak
> rem 如果你要安装,则执行以下这条命令
> nmake -f ms\ntdll.mak install   
> rem 清空编译的中间结果
> rem nmake -f ms\ntdll.mak clean

rem 是CMD中的注释命令】

这里的 --prefix 和 --openssldir 选项可以不需要,因为这两个选项是用来指定 OpenSSL 的安装路径的,我们只要编译,可以不用安装就可以使用了的。编译完成之后,在 OpenSSL 的根目录下就会生成一个【/out32dll】 的目录,里面包含了我们需要的文件 libeay32.dll 、libeay32.lib 、ssleay32.dll 、ssleay32.lib openssl.exe, 当然还有头文件所在的目录 【/inc32】。如下图所示:

然后我们就可以新建一个项目【例如用VS2010等】,测试 OpenSSL 了,但是这里编译出来的 OpenSSL 是 Release 版本的,很多符号信息都会被丢弃掉,在调试的过程中,如果想要进入OpenSSL内部调试它的代码,很多变量的信息就丢失了,如下图所示:

因此,调试起来就非常的不舒服,很多时候我们都需要看这些函数内部的变量信息,而现在却得不到,表示很不爽。

 

0x04 编译带符号的 OpenSSL【Debug 版本】

现在我们编译带符号的OpenSSL版本,并且添加很多的宏,这些宏使得 OpenSSL 在运行的过程中输出大量的对我们有用的信息,例如 TLS 协议中的重要参数信息: PreMasterKey, MasterKey, KEY_BLOCK 等等。

我们在配置 OpenSSL 的时候给它添加如下的宏:

  • DEBUG
  • _DEBUG
  • OPENSSL_DEBUG_KEYGEN
  • SSL_DEBUG
  • ALG_DEBUG
  • CIPHER_DEBUG
  • TLS_DEBUG
  • KSSL_DEBUG

具体的编译命令如下:

rem 编译 debug 版本,并且输出 大量LOG日志信息,包括 MasterKey 等。
> Perl Configure -DDEBUG -D_DEBUG -DOPENSSL_DEBUG_KEYGEN -DSSL_DEBUG -DALG_DEBUG -DCIPHER_DEBUG  -DTLS_DEBUG  -DKSSL_DEBUG debug-VC-WIN32 no-asm --prefix=C:\MyProgramFiles\OpenSSLv1.0.2h --openssldir=C:\MyProgramFiles\OpenSSLv1.0.2h\SSL
> ms\do_ms
> nmake -f ms\ntdll.mak

执行完以上命令之后,就生成了一个 Debug 版本的 OpenSSL,对应的 dll 文件和 lib 文件在 目录【/out32dll.dbg】中,而头文件还是在目录 【/inc32】中,这时候调试就会有符号信息了,

但是还有一个大坑,那就是运行时会出现如下错误:

OPENSSL_Uplink(0098E000,07): no OPENSSL_Applink 错误

找了很久之后,通过翻阅 OpenSSL 的源代码,自己想到了一个很好的解决方法,那就是把 :

E:\OpenSSL\openssl-OpenSSL_1_0_2h\crypto\bio\b_dump.c 文件中的一个宏直接改掉,

如下图所示:

因为这里的 UP_fwrite 是一个宏定义,而正是由于这个宏定义导致了 APPLINK的错误,所以我们把这个宏直接改掉,把UP_fwrite直接改成 fwrite 即可,然后再编译,程序就一切正常了,如下图所示:

 

0x05 输出结果对比

使用 Release 版本的 OpenSSL 的输出结果:

使用 Debug 版本的 OpenSSL 输出了非常多的调试信息,如下图所示:

具体信息如下:

// Client 端的输出

ssl_create_cipher_list() for 125 ciphers
        0: ECDH-RSA-AES256-GCM-SHA384 300c032 20 10
        1: ECDH-RSA-AES128-GCM-SHA256 300c031 20 10
        2: ECDHE-RSA-AES256-GCM-SHA384 300c030 80 1
        ......
        122: RC4-MD5 3000004 1 1
        123: NULL-SHA 3000002 1 1
        124: NULL-MD5 3000001 1 1
Applying rule 1 with 00000080/00000000/00000000/00000000/00000000 00000000 (-1)

Name: ECDH-RSA-AES256-GCM-SHA384:
Algo = 00000020/00000010/00002000/00000040/00000004 Algo_strength = 00000181

Name: ECDH-RSA-AES128-GCM-SHA256:
Algo = 00000020/00000010/00001000/00000040/00000004 Algo_strength = 00000181

...........

Name: ECDH-ECDSA-DES-CBC3-SHA:
Algo = 00000040/00000010/00000002/00000002/00000002 Algo_strength = 00000181

Name: DES-CBC3-SHA:
Algo = 00000001/00000001/00000002/00000002/00000002 Algo_strength = 00000181

Name: PSK-3DES-EDE-CBC-SHA:
Algo = 00000100/00000080/00000002/00000002/00000002 Algo_strength = 00000181
<ECDHE-RSA-AES256-GCM-SHA384>
<ECDHE-ECDSA-AES256-GCM-SHA384>

...........

<ECDH-RSA-DES-CBC3-SHA>
<ECDH-ECDSA-DES-CBC3-SHA>
<DES-CBC3-SHA>
<PSK-3DES-EDE-CBC-SHA>
socket created
address created
server connected
tls1_enc(1)
tls1_enc(0)
dec 58
02 00 00 36 03 03 EA 77 65 22 30 A6 92 36 8C 3C
8C 77 77 8F 05 DE 26 B4 4F 9D BE 07 AB 9E 57 AB
F4 68 4B FF 84 39 00 00 9D 00 00 0E FF 01 00 01
00 00 23 00 00 00 0F 00 01 01
tls1_enc(0)
dec 867
0B 00 03 5F 00 03 5C 00 03 59 30 82 03 55 30 82
02 3D A0 03 02 01 02 02 01 01 30 0D 06 09 2A 86
48 86 F7 0D 01 01 0B 05 00 30 7B 31 0B 30 09 06
03 55 04 06 13 02 43 4E 31 11 30 0F 06 03 55 04
08 0C 08 53 68 61 6E 67 48 61 69 31 11 30 0F 06
03 55 04 07 0C 08 53 68 61 6E 67 48 61 69 31 0D
30 0B 06 03 55 04 0A 0C 04 53 4A 54 55 31 0D 30
0B 06 03 55 04 0B 0C 04 53 4A 54 55 31 0B 30 09
06 03 55 04 03 0C 02 6D 6C 31 1B 30 19 06 09 2A
86 48 86 F7 0D 01 09 01 16 0C 73 6A 74 75 40 73
6A 74 75 2E 63 6E 30 1E 17 0D 31 38 30 37 32 38
31 34 32 30 35 31 5A 17 0D 31 39 30 37 32 38 31
34 32 30 35 31 5A 30 68 31 0B 30 09 06 03 55 04
06 13 02 43 4E 31 11 30 0F 06 03 55 04 08 0C 08
53 68 61 6E 67 48 61 69 31 0D 30 0B 06 03 55 04
0A 0C 04 53 4A 54 55 31 0D 30 0B 06 03 55 04 0B
0C 04 53 4A 54 55 31 0B 30 09 06 03 55 04 03 0C
02 6D 6C 31 1B 30 19 06 09 2A 86 48 86 F7 0D 01
09 01 16 0C 73 6A 74 75 40 73 6A 74 75 2E 63 6E
30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01
05 00 03 81 8D 00 30 81 89 02 81 81 00 F7 22 23
3C 4E DF EE BF AC A0 00 8A EA DE 5C BF B6 CF B9
2E D9 F5 04 39 48 34 79 01 04 BE E3 28 A0 C6 A4
D4 9A 92 BA 98 CF 77 05 44 C5 CB 56 F3 A1 FD DE
29 46 1D 88 D2 3E 6D 91 34 37 F4 67 9A 09 E1 C8
C0 1E 2D B0 DD 8A 34 A4 40 FA FD 1D 1D 0E 1D 8B
AF 2F 1D 19 7C C1 25 3E 04 3F B3 4D C6 79 66 39
40 E9 4E D2 85 19 0B 98 1F 6B F7 00 70 68 E9 18
F5 4B 42 E3 C9 C4 AF 75 49 D2 DA 3E A9 02 03 01
00 01 A3 7B 30 79 30 09 06 03 55 1D 13 04 02 30
00 30 2C 06 09 60 86 48 01 86 F8 42 01 0D 04 1F
16 1D 4F 70 65 6E 53 53 4C 20 47 65 6E 65 72 61
74 65 64 20 43 65 72 74 69 66 69 63 61 74 65 30
1D 06 03 55 1D 0E 04 16 04 14 A0 AC 52 D2 F2 A8
54 BF 3C F9 B2 71 57 44 8E 28 4F 85 FC EA 30 1F
06 03 55 1D 23 04 18 30 16 80 14 FD 98 DA AF 30
AC 6E F0 BA 99 36 36 40 98 35 55 C3 99 9D A7 30
0D 06 09 2A 86 48 86 F7 0D 01 01 0B 05 00 03 82
01 01 00 01 64 DD 87 2B 52 FD FF 07 F5 BA 8E 35
7D A7 3E 3F BC 4C F7 7F C9 92 03 60 47 9E 01 27
11 97 89 DF BD 50 D5 A1 A4 5A 06 00 84 9D 6D CA
F2 43 F9 A6 01 B3 49 64 6D B2 27 51 E4 AF 72 88
1F 0D D4 35 BA 28 76 9D 22 97 84 22 16 90 22 E6
02 15 AB CF 55 23 73 83 40 03 05 AD FB 88 AD 95
DC C8 D7 91 4C 32 B7 E5 8D 5D 82 C8 06 16 89 BB
57 23 A4 11 0A C1 8F AC 20 78 3E AC 72 11 1C D7
EB 7E E3 24 97 BA 8B CA D2 67 69 2D 8E 3C 88 42
1B A1 0F 0A 7F CD 49 57 A0 76 48 69 4D DE 94 58
3D 67 BF E2 05 FD D5 A7 72 60 3A FD 38 26 ED D7
4C 19 9E 4F B3 7D 7B 74 B5 6C AB 1A 27 8C 2A E7
E6 89 92 A7 C1 0A 89 A5 5A 11 73 B6 71 A5 E6 7F
E1 89 50 8A A9 F4 3E 95 1C 05 A5 72 A7 35 F6 4F
C3 5A 74 E5 4E ED B6 EF 0F CF 30 09 28 3D 11 9B
BF FA A3 3D 98 FE C2 0B 87 61 E7 E4 33 23 D5 F1
F8 38 FE
pkey,x = 032D2E28, 032CDF68
ssl_cert_type(x,pkey) = 0
cipher, alg, nc = AES256-GCM-SHA384, 1, 1, 1
tls1_enc(0)
dec 4
0E 00 00 00
tls1_generate_master_secret(032BD1E8,032CDE5C, 014FEFA8, 48)
Premaster Secret:
0000 - 03 03 d4 1f 37 33 73 d7-19 33 3e 41 bf 23 0c 9a   ....73s..3>A.#..
0010 - 62 38 ed 14 27 56 9e a7-fa ee a1 d4 37 95 bf bd   b8..'V......7...
0020 - e7 cd fd ba e7 f0 1e b1-40 a7 95 4a f6 c9 ab 54   ........@..J...T
Client Random:
0000 - a3 cd 3e bb 59 38 31 46-5f 07 97 92 3b 07 d5 37   ..>.Y81F_...;..7
0010 - 36 cd d8 dc 45 ed 01 67-b8 46 97 26 99 8c c1 55   6...E..g.F.&...U
Server Random:
0000 - ea 77 65 22 30 a6 92 36-8c 3c 8c 77 77 8f 05 de   .we"0..6.<.ww...
0010 - 26 b4 4f 9d be 07 ab 9e-57 ab f4 68 4b ff 84 39   &.O.....W..hK..9
Master Secret:
0000 - 76 f0 5b f0 1f 80 9e 49-c0 1d 6a 1f 63 20 86 d4   v.[....I..j.c ..
0010 - 2b 21 75 ba 5b 01 0e d1-60 c6 f9 b7 af 0c 71 fd   +!u.[...`.....q.
0020 - b3 f0 1d e0 01 d2 4e e2-e8 5f 62 88 98 e7 65 aa   ......N.._b...e.
tls1_generate_master_secret() complete
tls1_enc(1)
tls1_enc(1)
tls1_setup_key_block()
client random
A3 CD 3E BB 59 38 31 46 5F 07 97 92 3B 07 D5 37
36 CD D8 DC 45 ED 01 67 B8 46 97 26 99 8C C1 55
server random
EA 77 65 22 30 A6 92 36 8C 3C 8C 77 77 8F 05 DE
26 B4 4F 9D BE 07 AB 9E 57 AB F4 68 4B FF 84 39
pre-master
76 F0 5B F0 1F 80 9E 49 C0 1D 6A 1F 63 20 86 D4
2B 21 75 BA 5B 01 0E D1 60 C6 F9 B7 AF 0C 71 FD
B3 F0 1D E0 01 D2 4E E2 E8 5F 62 88 98 E7 65 AA
tls1_generate_key_block() ==> 48 byte master_key =
        76F05BF01F809E49C01D6A1F632086D42B2175BA5B010ED160C6F9B7AF0C71FDB3F01DE001D24EE2E85F628898E765AA

key block
D0 9E 36 21 BE 74 3E DF C3 0D B5 BA 01 E4 B1 DC
A4 79 1E 7D 2A 8D 4F 7E 0B F9 EB 67 39 B2 7F 18
C0 FD AC 39 28 10 EC 11 55 5E B0 AD A6 9E 9D 38
DB 3E 24 80 9D CE FD 77 9D 6E 71 64 44 71 E0 7F
C7 9F 28 48 59 9F A1 E1 BA 2D 78 99 B1 34 6E B6
2E 77 8B 4F 0B 88 CA A8 tls1_change_cipher_state(which= 18) w/
        alg= 1/1, comp= 00000000
        evp_cipher == 1008F0B0 ==? &d_cbc_ede_cipher3
        evp_cipher: nid, blksz= 901, 1, keylen=32, ivlen=12
        key_block: len= 88, data= d09e3621be743edfc30db5ba01e4b1dca4791e7d2a8d4f7e0bf9eb6739b27f18c0fdac392810ec11555eb0ada69e9d38db3e24809dcefd779d6e71644471e07fc79f2848599fa1e1ba2d7899b1346eb62e778b4f0b88caa8
which = 0012
mac key=EVP_CipherInit_ex(dd,c,key=,iv=,which)
        key= d09e3621be743edfc30db5ba01e4b1dca4791e7d2a8d4f7e0bf9eb6739b27f18
         iv= c79f2848599fa1e1ba2d7899
which = 0012
key=D0 9E 36 21 BE 74 3E DF C3 0D B5 BA 01 E4 B1 DC
A4 79 1E 7D 2A 8D 4F 7E 0B F9 EB 67 39 B2 7F 18

iv=C7 9F 28 48
tls1_enc(1)
EVP_Cipher(ds=032CF690,rec->data=032C77E0,rec->input=032C77E0,l=40) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: C79F2848442E2C6C0AA60B07
        rec->input= 01 00 00 82 00 80 ea 0e 14 00 00 0c df 67 a9 c1 b0 47 c5 5f b8 45 d5 f3 5d f5 79 92 9f ef 9a f8 8c 14 d3 e9 d5 87 f4 b1
        rec->data= 44 2e 2c 6c 0a a6 0b 07 da 74 5e 6f 16 56 f5 bc 5b e4 b1 a2 c1 31 66 e8 13 a9 2f d2 79 e8 1a d3 cf 9f a5 88 3f 1d dd df
tls1_enc(0)
dec 170
04 00 00 A6 00 00 1C 20 00 A0 E3 F1 7E 5C 48 EA
D0 D5 25 B8 77 E0 F7 8A F6 0A 49 18 21 3D ED 52
84 D5 B1 8F 0F A5 10 EE 09 AE 17 E0 A0 C7 70 CC
F0 DD 3B 46 A7 B8 00 3B 3A 80 37 24 05 85 C0 7D
73 12 BF AF 95 46 12 57 4A EF 26 10 96 C3 0A 44
80 88 D4 64 FF 2F ED 05 EA E6 BA 37 79 D4 A3 7E
34 8E 54 3F 85 52 27 0E 04 52 75 39 E3 D3 70 26
13 13 CB 7D 52 35 94 ED F2 3D 73 80 7F F1 2C A6
3D 4E 62 8C B0 44 4A 9C 2E AC DE 95 75 E2 79 34
AE 02 8C 18 51 3A 5C 81 66 9D B1 84 A3 E0 CD B1
9C 4E 6A B6 36 10 0D 31 FF 35
tls1_enc(0)
dec 1
01
tls1_change_cipher_state(which= 17) w/
        alg= 1/1, comp= 00000000
        evp_cipher == 1008F0B0 ==? &d_cbc_ede_cipher3
        evp_cipher: nid, blksz= 901, 1, keylen=32, ivlen=12
        key_block: len= 88, data= d09e3621be743edfc30db5ba01e4b1dca4791e7d2a8d4f7e0bf9eb6739b27f18c0fdac392810ec11555eb0ada69e9d38db3e24809dcefd779d6e71644471e07fc79f2848599fa1e1ba2d7899b1346eb62e778b4f0b88caa8
which = 0011
mac key=EVP_CipherInit_ex(dd,c,key=,iv=,which)
        key= c0fdac392810ec11555eb0ada69e9d38db3e24809dcefd779d6e71644471e07f
         iv= 599fa1e1ba2d7899b1346eb6
which = 0011
key=C0 FD AC 39 28 10 EC 11 55 5E B0 AD A6 9E 9D 38
DB 3E 24 80 9D CE FD 77 9D 6E 71 64 44 71 E0 7F

iv=59 9F A1 E1
tls1_enc(0)
EVP_Cipher(ds=032CF418,rec->data=032C3268,rec->input=032C3268,l=40) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: 599FA1E10000000000000000
        rec->input= 85 97 a5 75 ca b5 75 90 08 ad 86 3c e0 73 61 37 f1 ba 51 40 69 fe 6e fb f8 ee 13 c0 5b 70 68 ee eb 0c f1 8d d4 7a e2 64
        rec->data= 14 00 00 0c ce 42 da 39 00 b7 ed f3 c3 8e 60 b7 f8 ee 13 c0 5b 70 68 ee eb 0c f1 8d d4 7a e2 64 09 ae 17 e0 a0 c7 70 cc
dec 16
14 00 00 0C CE 42 DA 39 00 B7 ED F3 C3 8E 60 B7

Connected with AES256-GCM-SHA384 encryption
数字证书信息:
证书: /C=CN/ST=ShangHai/O=SJTU/OU=SJTU/CN=ml/emailAddress=sjtu@sjtu.cn
颁发者: /C=CN/ST=ShangHai/L=ShangHai/O=SJTU/OU=SJTU/CN=ml/emailAddress=sjtu@sjtu.cn
tls1_enc(0)
EVP_Cipher(ds=032CF418,rec->data=032C3268,rec->input=032C3268,l=38) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: 599FA1E18597A575CAB57590
        rec->input= 85 97 a5 75 ca b5 75 91 17 97 78 c4 a4 dc 28 0e 00 09 dd 21 ef 5f 28 c7 19 0a c2 c3 70 bc 9b 11 29 6e ec a0 bf bd
        rec->data= 73 65 72 76 65 72 2d 3e 63 6c 69 65 6e 74 28 c7 19 0a c2 c3 70 bc 9b 11 29 6e ec a0 bf bd e2 64 09 ae 17 e0 a0 c7
dec 14
73 65 72 76 65 72 2D 3E 63 6C 69 65 6E 74
接收消息成功:'server->client',共14个字节的数据
tls1_enc(1)
EVP_Cipher(ds=032CF690,rec->data=032C77E0,rec->input=032C77E0,l=43) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: C79F2848442E2C6C0AA60B08
        rec->input= 44 2e 2c 6c 0a a6 0b 07 66 72 6f 6d 20 63 6c 69 65 6e 74 2d 3e 73 65 72 76 65 72 d2 79 e8 1a d3 cf 9f a5 88 3f 1d dd df 06 0c 8e
        rec->data= 44 2e 2c 6c 0a a6 0b 08 2c c2 3e d4 3b d7 ac f7 26 d7 45 36 10 1d a1 d6 10 cc fd cd 24 8a 50 c7 ff 61 e3 cf a7 11 24 b4 f3 c3 18
消息'from client->server'发送成功,共发送了19个字节!
tls1_enc(1)
EVP_Cipher(ds=032CF690,rec->data=032C77E0,rec->input=032C77E0,l=26) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: C79F2848442E2C6C0AA60B09
        rec->input= 44 2e 2c 6c 0a a6 0b 08 01 00 3e d4 3b d7 ac f7 26 d7 45 36 10 1d a1 d6 10 cc
        rec->data= 44 2e 2c 6c 0a a6 0b 09 9d 8d 76 5f 99 8f 5e 13 be b2 0a 6c df a5 be 26 47 0c
请按任意键继续. . .
// Server 端的输出也类似,

ssl_create_cipher_list() for 125 ciphers
        0: ECDH-RSA-AES256-GCM-SHA384 300c032 20 10
        1: ECDH-RSA-AES128-GCM-SHA256 300c031 20 10

       ...........

        121: RC4-SHA 3000005 1 1
        122: RC4-MD5 3000004 1 1
        123: NULL-SHA 3000002 1 1
        124: NULL-MD5 3000001 1 1
Applying rule 1 with 00000080/00000000/00000000/00000000/00000000 00000000 (-1)

Name: ECDH-RSA-AES256-GCM-SHA384:
Algo = 00000020/00000010/00002000/00000040/00000004 Algo_strength = 00000181

Name: ECDH-RSA-AES128-GCM-SHA256:
Algo = 00000020/00000010/00001000/00000040/00000004 Algo_strength = 00000181

..........

Name: DES-CBC3-SHA:
Algo = 00000001/00000001/00000002/00000002/00000002 Algo_strength = 00000181

Name: PSK-3DES-EDE-CBC-SHA:
Algo = 00000100/00000080/00000002/00000002/00000002 Algo_strength = 00000181
<ECDHE-RSA-AES256-GCM-SHA384>
<ECDHE-ECDSA-AES256-GCM-SHA384>

...........

<ECDH-RSA-DES-CBC3-SHA>
<ECDH-ECDSA-DES-CBC3-SHA>
<DES-CBC3-SHA>
<PSK-3DES-EDE-CBC-SHA>
socket created
binded
begin listen
server: got connection from 10.162.143.68, port 15512, socket 384
tls1_enc(0)
dec 302
01 00 01 2A 03 03 A3 CD 3E BB 59 38 31 46 5F 07
97 92 3B 07 D5 37 36 CD D8 DC 45 ED 01 67 B8 46
97 26 99 8C C1 55 00 00 AC C0 30 C0 2C C0 28 C0
24 C0 14 C0 0A 00 A5 00 A3 00 A1 00 9F 00 6B 00
6A 00 69 00 68 00 39 00 38 00 37 00 36 00 88 00
87 00 86 00 85 C0 32 C0 2E C0 2A C0 26 C0 0F C0
05 00 9D 00 3D 00 35 00 84 C0 2F C0 2B C0 27 C0
23 C0 13 C0 09 00 A4 00 A2 00 A0 00 9E 00 67 00
40 00 3F 00 3E 00 33 00 32 00 31 00 30 00 9A 00
99 00 98 00 97 00 45 00 44 00 43 00 42 C0 31 C0
2D C0 29 C0 25 C0 0E C0 04 00 9C 00 3C 00 2F 00
96 00 41 00 07 C0 11 C0 07 C0 0C C0 02 00 05 00
04 C0 12 C0 08 00 16 00 13 00 10 00 0D C0 0D C0
03 00 0A 00 FF 01 00 00 55 00 0B 00 04 03 00 01
02 00 0A 00 1C 00 1A 00 17 00 19 00 1C 00 1B 00
18 00 1A 00 16 00 0E 00 0D 00 0B 00 0C 00 09 00
0A 00 23 00 00 00 0D 00 20 00 1E 06 01 06 02 06
03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03
02 03 03 02 01 02 02 02 03 00 0F 00 01 01
Server has 98 from 02D28530:
0F8B46E0:ECDHE-RSA-AES256-GCM-SHA384
0F8B4620:ECDHE-ECDSA-AES256-GCM-SHA384

...........

0F8B4050:ECDH-RSA-DES-CBC3-SHA
0F8B3E70:ECDH-ECDSA-DES-CBC3-SHA
0F8B30F0:DES-CBC3-SHA
rt=0 rte=0 dht=0 ecdht=0 re=1 ree=1 rs=0 ds=0 dhr=0 dhd=0
0:[00000080:00000001:00000101:00000085]0F8B46E0:ECDHE-RSA-AES256-GCM-SHA384
rt=0 rte=0 dht=0 ecdht=0 re=1 ree=1 rs=0 ds=0 dhr=0 dhd=0
0:[00000080:00000040:00000101:00000085]0F8B4620:ECDHE-ECDSA-AES256-GCM-SHA384
rt=0 rte=0 dht=0 ecdht=0 re=1 ree=1 rs=0 ds=0 dhr=0 dhd=0

...........

rt=0 rte=0 dht=0 ecdht=0 re=1 ree=1 rs=0 ds=0 dhr=0 dhd=0
0:[00000040:00000010:00000101:00000085]0F8B3ED0:ECDH-ECDSA-AES256-SHA
rt=0 rte=0 dht=0 ecdht=0 re=1 ree=1 rs=0 ds=0 dhr=0 dhd=0
1:[00000001:00000001:00000101:00000085]0F8B3C00:AES256-GCM-SHA384
tls1_enc(1)
rt=0 rte=0 dht=0 ecdht=0 re=1 ree=1 rs=0 ds=0 dhr=0 dhd=0
tls1_enc(1)
tls1_enc(1)
tls1_enc(0)
dec 134
10 00 00 82 00 80 EA 0E C9 02 FC DB 63 5B 1F F6
73 A4 88 20 4F BA 45 26 5D F5 79 92 9F EF 9A F8
8C 14 D3 E9 D5 87 F4 B1 06 0C 8E 9E F1 6A D3 AB
0A 80 88 2E 61 26 1D 7B D6 C8 52 64 9E 8C DC 4C
02 25 8B A5 9B 4B 1C 42 18 45 08 F7 26 8C DA 48
7B 7B 5B 9A DD D2 C1 4E 4A 36 01 0A 07 0B 33 B6
F4 24 49 2C 34 D5 5E 56 DE 5D F9 05 C0 8C 68 F4
A2 84 EA 8A 1F 52 53 54 D8 E2 93 90 1F 57 DC FB
C3 09 CA C8 C5 0F
tls1_generate_master_secret(02D62250,02D5D4BC, 02D62ACE, 48)
Premaster Secret:
0000 - 03 03 d4 1f 37 33 73 d7-19 33 3e 41 bf 23 0c 9a   ....73s..3>A.#..
0010 - 62 38 ed 14 27 56 9e a7-fa ee a1 d4 37 95 bf bd   b8..'V......7...
0020 - e7 cd fd ba e7 f0 1e b1-40 a7 95 4a f6 c9 ab 54   ........@..J...T
Client Random:
0000 - a3 cd 3e bb 59 38 31 46-5f 07 97 92 3b 07 d5 37   ..>.Y81F_...;..7
0010 - 36 cd d8 dc 45 ed 01 67-b8 46 97 26 99 8c c1 55   6...E..g.F.&...U
Server Random:
0000 - ea 77 65 22 30 a6 92 36-8c 3c 8c 77 77 8f 05 de   .we"0..6.<.ww...
0010 - 26 b4 4f 9d be 07 ab 9e-57 ab f4 68 4b ff 84 39   &.O.....W..hK..9
Master Secret:
0000 - 76 f0 5b f0 1f 80 9e 49-c0 1d 6a 1f 63 20 86 d4   v.[....I..j.c ..
0010 - 2b 21 75 ba 5b 01 0e d1-60 c6 f9 b7 af 0c 71 fd   +!u.[...`.....q.
0020 - b3 f0 1d e0 01 d2 4e e2-e8 5f 62 88 98 e7 65 aa   ......N.._b...e.
tls1_generate_master_secret() complete
tls1_enc(0)
dec 1
01
tls1_setup_key_block()
client random
A3 CD 3E BB 59 38 31 46 5F 07 97 92 3B 07 D5 37
36 CD D8 DC 45 ED 01 67 B8 46 97 26 99 8C C1 55
server random
EA 77 65 22 30 A6 92 36 8C 3C 8C 77 77 8F 05 DE
26 B4 4F 9D BE 07 AB 9E 57 AB F4 68 4B FF 84 39
pre-master
76 F0 5B F0 1F 80 9E 49 C0 1D 6A 1F 63 20 86 D4
2B 21 75 BA 5B 01 0E D1 60 C6 F9 B7 AF 0C 71 FD
B3 F0 1D E0 01 D2 4E E2 E8 5F 62 88 98 E7 65 AA
tls1_generate_key_block() ==> 48 byte master_key =
        76F05BF01F809E49C01D6A1F632086D42B2175BA5B010ED160C6F9B7AF0C71FDB3F01DE001D24EE2E85F628898E765AA

key block
D0 9E 36 21 BE 74 3E DF C3 0D B5 BA 01 E4 B1 DC
A4 79 1E 7D 2A 8D 4F 7E 0B F9 EB 67 39 B2 7F 18
C0 FD AC 39 28 10 EC 11 55 5E B0 AD A6 9E 9D 38
DB 3E 24 80 9D CE FD 77 9D 6E 71 64 44 71 E0 7F
C7 9F 28 48 59 9F A1 E1 BA 2D 78 99 B1 34 6E B6
2E 77 8B 4F 0B 88 CA A8 tls1_change_cipher_state(which= 33) w/
        alg= 1/1, comp= 00000000
        evp_cipher == 0FA8F0B0 ==? &d_cbc_ede_cipher3
        evp_cipher: nid, blksz= 901, 1, keylen=32, ivlen=12
        key_block: len= 88, data= d09e3621be743edfc30db5ba01e4b1dca4791e7d2a8d4f7e0bf9eb6739b27f18c0fdac392810ec11555eb0ada69e9d38db3e24809dcefd779d6e71644471e07fc79f2848599fa1e1ba2d7899b1346eb62e778b4f0b88caa8
which = 0021
mac key=EVP_CipherInit_ex(dd,c,key=,iv=,which)
        key= d09e3621be743edfc30db5ba01e4b1dca4791e7d2a8d4f7e0bf9eb6739b27f18
         iv= c79f2848599fa1e1ba2d7899
which = 0021
key=D0 9E 36 21 BE 74 3E DF C3 0D B5 BA 01 E4 B1 DC
A4 79 1E 7D 2A 8D 4F 7E 0B F9 EB 67 39 B2 7F 18

iv=C7 9F 28 48
tls1_enc(0)
EVP_Cipher(ds=02D73CB0,rec->data=02D68058,rec->input=02D68058,l=40) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: C79F28480000000000000000
        rec->input= 44 2e 2c 6c 0a a6 0b 07 da 74 5e 6f 16 56 f5 bc 5b e4 b1 a2 c1 31 66 e8 13 a9 2f d2 79 e8 1a d3 cf 9f a5 88 3f 1d dd df
        rec->data= 14 00 00 0c df 67 a9 c1 b0 47 c5 5f b8 45 d5 f3 13 a9 2f d2 79 e8 1a d3 cf 9f a5 88 3f 1d dd df 06 0c 8e 9e f1 6a d3 ab
dec 16
14 00 00 0C DF 67 A9 C1 B0 47 C5 5F B8 45 D5 F3

tls1_enc(1)
tls1_setup_key_block()
tls1_enc(1)
tls1_change_cipher_state(which= 34) w/
        alg= 1/1, comp= 00000000
        evp_cipher == 0FA8F0B0 ==? &d_cbc_ede_cipher3
        evp_cipher: nid, blksz= 901, 1, keylen=32, ivlen=12
        key_block: len= 88, data= d09e3621be743edfc30db5ba01e4b1dca4791e7d2a8d4f7e0bf9eb6739b27f18c0fdac392810ec11555eb0ada69e9d38db3e24809dcefd779d6e71644471e07fc79f2848599fa1e1ba2d7899b1346eb62e778b4f0b88caa8
which = 0022
mac key=EVP_CipherInit_ex(dd,c,key=,iv=,which)
        key= c0fdac392810ec11555eb0ada69e9d38db3e24809dcefd779d6e71644471e07f
         iv= 599fa1e1ba2d7899b1346eb6
which = 0022
key=C0 FD AC 39 28 10 EC 11 55 5E B0 AD A6 9E 9D 38
DB 3E 24 80 9D CE FD 77 9D 6E 71 64 44 71 E0 7F

iv=59 9F A1 E1
tls1_enc(1)
EVP_Cipher(ds=02D74BB8,rec->data=02D6C5D0,rec->input=02D6C5D0,l=40) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: 599FA1E18597A575CAB57590
        rec->input= 01 00 00 a6 00 00 1c 20 14 00 00 0c ce 42 da 39 00 b7 ed f3 c3 8e 60 b7 f6 0a 49 18 21 3d ed 52 84 d5 b1 8f 0f a5 10 ee
        rec->data= 85 97 a5 75 ca b5 75 90 08 ad 86 3c e0 73 61 37 f1 ba 51 40 69 fe 6e fb f8 ee 13 c0 5b 70 68 ee eb 0c f1 8d d4 7a e2 64
tls1_enc(1)
EVP_Cipher(ds=02D74BB8,rec->data=02D6C5D0,rec->input=02D6C5D0,l=38) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: 599FA1E18597A575CAB57591
        rec->input= 85 97 a5 75 ca b5 75 90 73 65 72 76 65 72 2d 3e 63 6c 69 65 6e 74 6e fb f8 ee 13 c0 5b 70 68 ee eb 0c f1 8d d4 7a
        rec->data= 85 97 a5 75 ca b5 75 91 17 97 78 c4 a4 dc 28 0e 00 09 dd 21 ef 5f 28 c7 19 0a c2 c3 70 bc 9b 11 29 6e ec a0 bf bd
消息'server->client'发送成功,共发送了14个字节!
tls1_enc(0)
EVP_Cipher(ds=02D73CB0,rec->data=02D68058,rec->input=02D68058,l=43) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: C79F2848442E2C6C0AA60B07
        rec->input= 44 2e 2c 6c 0a a6 0b 08 2c c2 3e d4 3b d7 ac f7 26 d7 45 36 10 1d a1 d6 10 cc fd cd 24 8a 50 c7 ff 61 e3 cf a7 11 24 b4 f3 c3 18
        rec->data= 66 72 6f 6d 20 63 6c 69 65 6e 74 2d 3e 73 65 72 76 65 72 cd 24 8a 50 c7 ff 61 e3 cf a7 11 24 b4 f3 c3 18 9e f1 6a d3 ab 0a 80 88
dec 19
66 72 6F 6D 20 63 6C 69 65 6E 74 2D 3E 73 65 72
76 65 72
接收消息成功:'from client->server',共19个字节的数据
tls1_enc(1)
EVP_Cipher(ds=02D74BB8,rec->data=02D6C5D0,rec->input=02D6C5D0,l=26) ==>
        EVP_CIPHER_CTX: 0 buf_len, 32 key_len [8 128], 12 iv_len
                IV: 599FA1E18597A575CAB57592
        rec->input= 85 97 a5 75 ca b5 75 91 01 00 78 c4 a4 dc 28 0e 00 09 dd 21 ef 5f 28 c7 19 0a
        rec->data= 85 97 a5 75 ca b5 75 92 3a 0c 5d d4 0c 9d e9 8b ba 45 d5 39 de 60 47 64 71 b8

可以看出,使用 Debug 版本的 OpenSSL 对于我们调试来说,非常的方便。

 

0x06 调试 OpenSSL 的源代码

Client 端的源代码:

// 参考链接: https://blog.csdn.net/ljttianqin/article/details/73498453
#include "TLS_Client.h"

#include <WinSock2.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/ssl3.h>

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

#pragma comment(lib, "WS2_32.lib")

#define MAXBUF 1024

void ShowCerts(SSL * ssl)
{
	X509 *cert;
	char *line;

	cert = SSL_get_peer_certificate(ssl);
	if (cert != NULL) {
		printf("数字证书信息:\n");
		line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
		printf("证书: %s\n", line);
		//free(line);
		line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
		printf("颁发者: %s\n", line);
		//free(line);
		X509_free(cert);
	}
	else
		printf("无证书信息!\n");
}

int main(int argc, char **argv)
{
	int sockfd, len;
	struct sockaddr_in dest;
	char buffer[MAXBUF + 1] = { 0 };
	SSL_CTX *ctx;
	SSL *ssl;
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	SSL_METHOD *method = NULL;
	SSL_CIPHER* cipher = NULL;
	SSL_SESSION *session = NULL;

	/* SSL 库初始化,参看 ssl-server.c 代码 */
	SSL_library_init();
	OpenSSL_add_all_algorithms();
	SSL_load_error_strings();
	method = TLSv1_2_client_method();
	ctx = SSL_CTX_new(method);
	if (ctx == NULL) 
	{
		ERR_print_errors_fp(stdout);
	}

	/* 创建一个 socket 用于 tcp 通信 */
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);

	if (err != 0)//返回0表示成功
	{
		return 0;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		WSACleanup();
		return 0;
	}

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("Socket");
		exit(errno);
	}
	printf("socket created\n");

	/* 初始化服务器端(对方)的地址和端口信息 */
	dest.sin_family = AF_INET;
	//dest.sin_addr.s_addr = inet_addr("127.0.0.1");
	//dest.sin_addr.s_addr = inet_addr("localhost");
	//dest.sin_addr.s_addr = inet_addr("192.168.0.123"); // 使用 Npcap Lookback Adapter 只能写本机IP地址
	dest.sin_addr.s_addr = inet_addr("10.162.143.68");

	dest.sin_port = htons(60005);

	printf("address created\n");

	/* 连接服务器 */
	if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) 
	{
		perror("Connect ");
		exit(errno);
	}
	printf("server connected\n");

	/* 基于 ctx 产生一个新的 SSL */
	ssl = SSL_new(ctx);
	SSL_set_fd(ssl, sockfd);
	
	// 这里可以改变默认使用的密码套件
	
	//err = SSL_set_cipher_list(ssl, "TLS_RSA_WITH_AES_128_GCM_SHA256");
	// 指定使用的密码套件
	// Wireshark 中显示的名称: TLS_RSA_WITH_AES_128_GCM_SHA256
	// 代码中显示的名称:AES128-GCM-SHA256
	//err = SSL_set_cipher_list(ssl, "AES128-GCM-SHA256");
	//if (err)
	//{
	//	puts("Set cipher failed.");
	//}

	/* 建立 SSL 连接 */
	if (SSL_connect(ssl) == -1)
		ERR_print_errors_fp(stderr);
	else 
	{
		printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
		ShowCerts(ssl);
	}
	
	/* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
	//bzero(buffer, MAXBUF + 1);
	/* 接收服务器来的消息 */
	len = SSL_read(ssl, buffer, MAXBUF);
	if (len > 0)
		printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len);
	else 
	{
		printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
		goto finish;
	}

	//bzero(buffer, MAXBUF + 1);
	memset(buffer, 0, MAXBUF);
	strcpy(buffer, "from client->server");
	/* 发消息给服务器 */
	len = SSL_write(ssl, buffer, strlen(buffer));
	if (len < 0)
		printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));
	else
		printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);

finish:
	/* 关闭连接 */
	SSL_shutdown(ssl);
	SSL_free(ssl);
	closesocket(sockfd);
	SSL_CTX_free(ctx);
	//fclose(fSession);
	return 0;

}

Server 端的源代码:


// https://blog.csdn.net/ljttianqin/article/details/73498453

#include "TLS_Server.h"


#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#pragma comment(lib, "WS2_32.lib")

#define MAXBUF 1024


int main(int argc, char **argv)
{
	//int sockfd, new_fd;
	SOCKET sockfd, new_fd;
	int len;
	struct sockaddr_in my_addr, their_addr;
	unsigned int myport = 60005, lisnum = 2;
	char buf[MAXBUF + 1];
	SSL_CTX *ctx;
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	SSL_METHOD *method = NULL;
	SSL_CIPHER* cipher = NULL;
	SSL_SESSION *session = NULL;

	/* SSL 库初始化 */
	SSL_library_init();
	/* 载入所有 SSL 算法 */
	OpenSSL_add_all_algorithms();
	/* 载入所有 SSL 错误消息 */
	SSL_load_error_strings();
	/* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */
	//ctx = SSL_CTX_new(SSLv23_server_method());
	//ctx = SSL_CTX_new(SSLv23_server_method());

	method = TLSv1_2_server_method();
	ctx = SSL_CTX_new(method);
	/* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */
	if (ctx == NULL) {
		ERR_print_errors_fp(stdout);
		exit(1);
	}
	/* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */
	if (SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM) <= 0) 
	{
		ERR_print_errors_fp(stdout);
		exit(1);
	}

	//载入私钥密码,否则终端提示用户手动输入密码
	SSL_CTX_set_default_passwd_cb_userdata(ctx, "123456");

	/* 载入用户私钥 */
	if (SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) <= 0) 
	{
		ERR_print_errors_fp(stdout);
		exit(1);
	}
	  
	/*或者
	#include <openssl/ssl.h>
	void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
	void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
	int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata);
	int pem_passwd_cb(char *buf, int size, int rwflag, void *password)
	{
	strncpy(buf, (char *)(password), size);
	buf[size - 1] = '\0';
	return(strlen(buf));
	}
	*/
	//SSL_CTX_set_default_passwd_cb_userdata(ctx, "123456");

	/* 检查用户私钥是否正确 */
	if (!SSL_CTX_check_private_key(ctx)) 
	{
		ERR_print_errors_fp(stdout);
		exit(1);
	}

	/* 开启一个 socket 监听 */
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		return 0;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		WSACleanup();
		return 0;
	}

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
	{
		perror("socket");
		exit(1);
	}
	else
		printf("socket created\n");

	my_addr.sin_family = AF_INET;
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_addr("10.32.16.174");
	//my_addr.sin_addr.s_addr = inet_addr("192.168.56.1");
	my_addr.sin_port = htons(myport);

	if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) 
	{
		perror("bind");
		exit(1);
	}
	else
		printf("binded\n");

	if (listen(sockfd, lisnum) == -1) 
	{
		perror("listen");
		exit(1);
	}
	else
		printf("begin listen\n");

	while (1) 
	{
		SSL *ssl;
		len = sizeof(struct sockaddr);

		/* 等待客户端连上来 */
		if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1) 
		{
			perror("accept");
			exit(errno);
		}
		else
			printf("server: got connection from %s, port %d, socket %d\n",
				inet_ntoa(their_addr.sin_addr),
				ntohs(their_addr.sin_port), new_fd);

		/* 基于 ctx 产生一个新的 SSL */
		ssl = SSL_new(ctx);
		/* 将连接用户的 socket 加入到 SSL */
		SSL_set_fd(ssl, new_fd);

		// 客户端或服务端只要有一方指定即可
		//err = SSL_set_cipher_list(ssl, "AES128-GCM-SHA256");
		//if (err)
		//{
		//	puts("Set cipher failed.");
		//}


		/* 建立 SSL 连接 */
		if (SSL_accept(ssl) == -1)
		{
			perror("accept");
			closesocket(new_fd);
			break;
		}

		/* 开始处理每个新连接上的数据收发 */
		//bzero(buf, MAXBUF + 1);
		memset(buf, 0, MAXBUF);
		strcpy(buf, "server->client");
		/* 发消息给客户端 */
		len = SSL_write(ssl, buf, strlen(buf));

		if (len <= 0) 
		{
			printf
				("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
					buf, errno, strerror(errno));
			goto finish;
		}
		else
			printf("消息'%s'发送成功,共发送了%d个字节!\n",
				buf, len);

		//bzero(buf, MAXBUF + 1);
		memset(buf, 0, MAXBUF);
		/* 接收客户端的消息 */
		len = SSL_read(ssl, buf, MAXBUF);
		if (len > 0)
			printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);
		else
			printf ("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
	/* 处理每个新连接上的数据收发结束 */
	finish:
		/* 关闭 SSL 连接 */
		SSL_shutdown(ssl);
		/* 释放 SSL */
		SSL_free(ssl);
		/* 关闭 socket */
		closesocket(new_fd);
	}

	/* 关闭监听的 socket */
	closesocket(sockfd);
	WSACleanup();
	/* 释放 CTX */
	SSL_CTX_free(ctx);
	return 0;

}

 

0x07 调试 OpenSSL 的相关配置

在我们的项目中,使用的是 VS2015,具体配置信息是:

step1: 设置 OpenSSL 头文件所在路径

【右键项目名称】->【属性】->【C/C++】->【常规】->【附加包含目录】->【填写 inc32所在的路径】

在本项目里,配置如下:

step2: 设置 OpenSSL 库文件【xxx.lib】所在路径:

【右键项目名称】->【属性】->【链接器】->【常规】->【附加库目录】->【填写 out32dll.dbg 所在的路径】

在本项目里,配置如下:

step3: 设置 OpenSSL 的依赖项【 lib 文件】:

【右键项目名称】->【属性】->【链接器】->【输入】->【附加依赖项】->【libeay32.lib;ssleay32.lib】

在本项目里,配置如下:

 

step4: 复制 OpenSSL 的 DLL 文件:

把 OpenSSL 的 DLL 文件复制到我们的工程目录中,一般是放在 Debug 目录,不过,如果把 VS 设置成 Release 模式的话,要放到 Release 目录中,现在我们设置的是 Debug 模式,于是把相应的 DLL 复制到【/Debug】目录即可,如下图所示:

客户端与服务端的配置都一样,配置好之后就可以编译调试了。

当然,还需要自己手动去生成一个服务端的证书和密钥等信息,这里我就讲解了,具体过程可以参考如下链接:

https://blog.csdn.net/ljttianqin/article/details/73016014

建议最好在 Linux 上创建这个证书。

这个证书最后需要放在服务端,如下图所示【注意路径】:

 

0x08 使用 Wireshark 抓包分析 TLS 协议

由于我的 Client 和 Server 都是在本机上的,所以我们用 Wireshark 抓本机的数据包还需要一些设置,具体请参考以下链接:

https://www.cnblogs.com/lvdongjie/p/6110183.html

现在默认你已经可以抓取本机和本机通信的数据包了,现在打开 Wireshark, 点击 Npcap Loopback Adapter 网卡,如下图所示:

然后再 过去框中输入:tcp && ip.addr == 10.162.143.68 , 点击 Apply【或者直接按回车,新版的 Wireshark 可以直接按回车】,如下图所示:

然后启动服务器,等服务器开始监听端口,如下图所示:

最后再启动 客户端,它们就自动的开始通信了,如下图所示:

不过要注意设置自己的 Client 的 IP地址为本机的IP地址,如下图所示:

最后就可以在Wireshark中看到我们刚才的通信过程了,如下图所示:

这个通信的过程包括 TLS 协议的 握手过程 和 数据传输 过程。

 

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值