在 libgcrypt 共享库中,在 AES 加密/解密操作期间访问查找表。在 AES 加密的情况下,1KB 查找表(定义为共享库中的静态 const u32 encT),在 AES 解密的情况下,1KB + 256 字节查找表(定义为
static const struct
{
u32 T[256];
byte inv_sbox[256];
} dec_tables inside shared library) are used.
作为共享库的静态成员,encT 和 dec_tables 将放置在哪里?在代码部分或任何其他部分?
当我用 nm 命令检查时,它显示 r ,表示只读。
nm /usr/local/lib/libgcrypt.so | grep encT
00091ae0 r encT
nm /usr/local/lib/libgcrypt.so | grep dec_tables
000915e0 r dec_tables
对于共享库,只读部分和代码部分是否相同?
我制作了一个示例程序来执行 AES 解密,并了解执行 AES 解密的程序的控制流程是什么。
gcryError = gcry_cipher_decrypt(
gcryCipherHd, // gcry_cipher_hd_t
dec_out, // void *
txtLength, // size_t
enc_out, // const void *
txtLength); // size_t
这是我发现的,
gcry_cipher_decrypt (visibility.c ) -->
_gcry_cipher_decrypt (cipher.c) -->
static cipher_decrypt (cipher.c) -->
static do_ecb_decrypt (cipher.c) -->
static do_ecb_crypt (cipher.c) -->
static do_decrypt (rijndael.c) -->
static do_decrypt_fn (rijndael.c)
在内部,do_decrypt_fn 函数最终解密操作是通过访问 dec_tables.T 和 dec_tables.inv_sbox 来执行的。
// few lines are added for reference
static unsigned int
do_decrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b,
const unsigned char *a)
{
sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[1][3] ^ sb[3];
/* Last round is special. */
sb[0] = inv_sbox[(byte)(sa[0] >> (0 * 8))] << (0 * 8);
sb[1] = inv_sbox[(byte)(sa[0] >> (1 * 8))] << (1 * 8);
sb[2] = inv_sbox[(byte)(sa[0] >> (2 * 8))] << (2 * 8);
sb[3] = inv_sbox[(byte)(sa[0] >> (3 * 8))] << (3 * 8);
sa[0] = sb[0] ^ rk[0][0];
这里,dec_tables 定义在 rijndael-tables.h 中,这个头文件包含在 rijndael.c 文件中。
static const struct
{
u32 T[256];
byte inv_sbox[256];
} dec_tables =
{
{
0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
...},
{
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
...}
#define decT dec_tables.T
#define inv_sbox dec_tables.inv_sbox
这是我对你的问题。
- 作为静态类型,所有这些静态函数和静态数据 dec_tables 在共享库模块之外都是不可见的。那么它们是如何定位以用于解密的呢?
我认为 encT 和 dec_tables 的这个 OFFSET 被某些函数或在某些计算中用来定位 dec_tables 以执行 AES 解密。 我对吗 ?
谁能解释使用 readelf/objdump/nm 或其他方式,共享库如何使用这些 OFFSET 来定位用于 AES 加密/解密的静态数据(encT/dec_tables)?
或者
- 这些 OFFSET 在任何意义上对定位 encT/dec_tables 静态数据有用吗?
我不知道 GOT 或 PLT 如何与 OFFSET 一起使用。有没有办法使用这些关于 GOT/PLT 的 OFFSET 来定位这些静态数据?
我正在使用 Ubuntu 16.06,gcc-4.9。
任何解决上述疑惑的链接/示例程序都会有很大帮助。提前致谢。