Bài giảng Lập trình an toàn - Lương Ánh Hoàng

7.1 Phát hiện thay đổi mã lệnh Hạn chế - De bị đánh bại nếu sử dụng hash vì cracker cũng có thê tính lại giá trị băm và sửa file cho chính xác. - Nếu sử dụng HMAC thì phải lưu mật khẩu ờ đâu đó • Lưu trong file: Cũng sè bị cracker dò ra • Lưu trên internet: cân có kết nổi internet và dễ dàng bị dò ra nếu dùng sniffer. • CURL 7.2 Che giấu mã Mục tiêu - Gây khó khăn cho quá trình dịch ngược và phân tích bằng các disassembler (Obfuscating code). Windasm, OllyDbg, IDA - Che giấu các cấu trúc điêu khiên quan trọng trong chưoĩìg trình. • Cấu trúc điêu kiện • Cấu trúc lặp Kỹ thuật - cân sự hồ trợ của trình biên dịch - Thực hiện ở mức hợp ngừ - Sừ dụng các điều kiện so sánh "bất thường” • So sánh khác thay vì bằng • Vòng lặp giâm thay vì tăng. • Vòng lặp có chĩ só tăng khác 1.

pdf131 trang | Chia sẻ: hachi492 | Ngày: 07/01/2022 | Lượt xem: 360 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Bài giảng Lập trình an toàn - Lương Ánh Hoàng, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ở  mức  thấp  một  cách  tập  trung,  dễ  dàng.   •  Tệp  tiêu  đề  .   •  Tệp  thư  viện:  libeay32.lib,  ssleay32.lib   •  Mã  hóa  AES  với  OpenSSL  EVP.   •  Khởi  tạo  khóa,  vector  khởi  tạo,  salt  với  EVP_BytesToKey  hoặc  tự  chọn  một  bộ  Key,  IV  nào  đó.   •  Khởi  tạo  ngữ  cảnh  mã  hóa  với  hàm  EVP_EncryptInit_ex.   •  Khởi  tạo  ngữ  cảnh  giải  mã  với  hàm  EVP_DecryptInit_ex.   •  Mã  hóa  dữ  liệu  bằng  việc  liên  tục  gọi  hàm  EVP_EncryptUpdate,  kết  thúc  quá  trình  mã  hóa  bằng  hàm  EVP_EncryptFinal_ex.   •  Giải  mã  dữ  liệu  bằng  việc  liên  tục  gọi  hàm  EVP_DecryptUpdate,  kết  thúc  quá  trình  giải  mã  bằng  hàm  EVP_DecryptFinal_ex.   4.5  Mã  hóa  đối  xứng  với  OpenSSL   65   •  VD   •  Sinh  key  và  iv  bằng  hàm  EVP_BytesToKey   char          key[32];   char          iv[32];       char  *  key_data  =  “nopass”;     unsigned  int  salt[]  =  {12345,  54321};   EVP_BytesToKey(EVP_aes_256_cbc(),  EVP_sha1(),  salt,  key_data,  6,  1,  key,   iv);   •  Khởi  tạo  ngữ  cảnh  mã  hóa  với  key  và  iv  đã  chọn   EVP_CIPHER_CTX  e_ctx;   EVP_CIPHER_CTX_init(&e_ctx);   EVP_EncryptInit_ex(&e_ctx,  EVP_aes_256_cbc(),NULL,  key,  iv);   •  Khởi  tạo  ngữ  cảnh  giải  mã  với  key  và  iv  đã  chọn   EVP_CIPHER_CTX  d_ctx;   EVP_CIPHER_CTX_init(&d_ctx);   EVP_DecryptInit_ex(&d_ctx,  EVP_aes_256_cbc(),NULL,  key,  iv);   4.5  Mã  hóa  đối  xứng  với  OpenSSL   66   •  VD  (tiếp)   •  Mã  hóa  với  ngữ  cảnh  đã  được  khởi  tạo   char  *    plaintext=“Hello”;   int  len  =  strlen(plaintext);   char  ciphertext[1024];   int    c_len  =  0,  f_len  =  0;   /*  Gọi  lại  hàm  này  để  cho  phép  OpenSSL  sử  dụng  lại  ngữ  cảnh  phiên  mã     hóa  trước  */   EVP_EncryptInit_ex(e,  NULL,  NULL,  NULL,  NULL);   //  Mỗi  chu  kỳ  Update,  c_len  sẽ  chứa  số  byte  của  xâu  mã  được   EVP_EncryptUpdate(e,  ciphertext,  &c_len,  plaintext,  len);   //  Cuối  chu  kỳ  Update,  f_len  sẽ  chưa  số  byte  còn  lại  của  xâu  mã   EVP_EncryptFinal_ex(e,  ciphertext+c_len,  &f_len);   4.5  Mã  hóa  đối  xứng  với  OpenSSL   67   •  VD  (tiếp)   •  Giải  mã  với  ngữ  cảnh  đã  được  khởi  tạo   char  plaintext[1024];   int  p_len  =  0;   /*  Gọi  lại  hàm  này  để  cho  phép  OpenSSL  sử  dụng  lại  ngữ  cảnh  phiên  giãi   mã    hóa  trước  */   EVP_DecryptInit_ex(e,  NULL,  NULL,  NULL,  NULL);   //  Giải  mã  với  ciphertext  và  len  được  cung  cấp  trước   EVP_DecryptUpdate(e,  plaintext,  &p_len,  ciphertext,  *len);   //  Kết  thúc  quá  trình  giải  mã,  cập  nhật  dữ  liệu  còn  lại  vào  plaintext.   EVP_DecryptFinal_ex(e,  plaintext+p_len,  &f_len);   4.5  Mã  hóa  đối  xứng  với  OpenSSL   68   •  Thư  viện  CryptoAPI   •  Cung  cấp  các  hàm  mật  mã  học  cơ  bản  thông  qua  các  Cryptographic  Service  Providers  (CSP).     •  Microsoft  Base  Cryptographic  Service  Provider:  RC2,  RC4,  DES   •  Microsoft  Enhanced  Cryptographic  Service  Provider:  Triple-­‐DES   •  Microsoft  AES  Cryptographic  Service  Provider:  AES   •    •  Cung  cấp  các  hàm  mã  hóa  và  giải  mã  chứng  thư  số,  và  đồng  thời  bổ  sung  các  hàm  băm.   •  Cung  cấp  các  hàm  quản  lý  và  lưu  trữ  chứng  thư  số.   •  Các  hàm  mã  thông  điệp  hóa  mức  cao  (Simpli}ied  Message  Functions).   •  Các  hàm  mã  hóa  thông  điệp  mức  thấp  (Low-­‐Level  Message  Functions).   4.6  Microsoft  Crypto  API   69   •  Thư  viện  CryptoAPI   4.6  Microsoft  Crypto  API   70   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Tệp  tiêu  đề  wincript.h   •  Thư  viện  Crypt32.lib   •  Trình  tự  sử  dụng     4.6  Microsoft  Crypto  API   71   Khởi  tạo   Provider   Tạo  khóa   • Ngẫu  nhiên   • Từ  mật  khẩu   • Từ  bên  ngoài   Đặt  chế  độ  mã   • CBC   • ECB   •    Thiết  lập  vector   khởi  tạo   Thực  hiện  Mã   hóa/Giải  mã   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Khởi  tạo  ngữ  cảnh  Provider  thông  qua  hàm  CryptAcquireContext    BOOL  WINAPI  CryptAcquireContext(__out  HCRYPTPROV*  phProv,            __in  LPCTSTR  pszContainer,            __in  LPCTSTR  pszProvider,            __in  DWORD  dwProvType,            __in  DWORD  dwFlags  );  VD:   HCRYPTPROV    hProvider;   if  (!CryptAcquireContext(&hProvider,            0,            MS_ENH_RSA_AES_PROV,            PROV_RSA_AES,                                                        CRYPT_VERIFYCONTEXT))        return  0;       4.6  Microsoft  Crypto  API   72   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Sử  dụng  Key  thông  qua  một  trong  ba  hàm.  Kết  quả  trả  về  là  đối  tượng  HCRYPTKEY   •  CryptGenKey(  ):  Sinh  khóa  ngẫu  nhiên.   •  CryptDeriveKey(  ):  Sinh  khóa  từ  mật  khẩu.   •  CryptImportKey(  )  :  Sinh  khóa  từ  một  đối  tượng  trong  bộ  nhớ.    VD1.  Sinh  khóa  ngẫu  nhiên     DWORD  dwFlags;     HCRYPTKEY  hKey;     DWORD  dwSize  =  256;     dwFlags  =  ((dwSize  <<  16)  &  0xFFFF0000)  |  CRYPT_EXPORTABLE;     if  (!CryptGenKey(hProvider,  CALG_AES_256,  dwFlags,  &hKey))  return  0;   4.6  Microsoft  Crypto  API   73   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   VD2.  Sinh  khóa  từ  mật  khẩu:  Cần  phải  băm  mật  khẩu  và  truyền  vào  hàm  CryptDeriveKey   char    *  password  =  “nopass”;       BOOL  bResult;     DWORD  cbData;     HCRYPTKEY  hKey;      //  Lưu  Key   HCRYPTHASH  hHash;    //  Lưu  giá  trị  băm  của  mật  khẩu   if  (!CryptCreateHash(hProvider,  CALG_SHA1,  0,  0,  &hHash))  //  Khởi  tạo  hàm  băm    return  0;     cbData  =  lstrlen(password)  *  sizeof(TCHAR);     if  (!CryptHashData(hHash,  (BYTE  *)password,  cbData,  0))    //  Băm  mật  khẩu    {        CryptDestroyHash(hHash);        return  0;      }   //  Tạo  key  từ  giá  trị  băm  của  mật  khẩu   bResult  =  CryptDeriveKey(hProvider,  CALG_AES_256,  hHash,  CRYPT_EXPORTABLE,   &hKey);     CryptDestroyHash(hHash);     4.6  Microsoft  Crypto  API   74   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Thiết  lập  chế  độ  mã  hóa  CBC  với  hàm  CryptSetKeyParam    DWORD  dwMode  =  CRYPT_MODE_CBC;    CryptSetKeyParam(hKey,  KP_MODE,  (BYTE  *)&dwMode,  0);   •  Sinh  ngẫu  nhiên  vector  khởi  tạo  (IV)   BOOL  bResult;        //  Lưu  kết  quả   BYTE  *pbTemp;      //  Lưu  vector  khởi  tạo   DWORD  dwBlockLen,  dwDataLen;     dwDataLen  =  sizeof(dwBlockLen);   //  Lấy  kích  thước  block  của  thuật  toán  mã  hóa    if  (!CryptGetKeyParam(hKey,  KP_BLOCKLEN,  (BYTE  *)&dwBlockLen,  &dwDataLen,   0))  return  0;   dwBlockLen  /=  8;     if  (!(pbTemp  =  (BYTE  *)LocalAlloc(LMEM_FIXED,  dwBlockLen)))    return  FALSE;   //  Sinh  ngẫu  nhiên  IV     bResult  =  CryptGenRandom(hProvider,  dwBlockLen,  pbTemp);   //  Thiết  lập  IV   bResult  =  CryptSetKeyParam(hKey,  KP_IV,  pbTemp,  0);     LocalFree(pbTemp);     4.6  Microsoft  Crypto  API   75   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Mã  hóa  với  CryptEncrypt   •  Với  các  giải  thuật  mã  hóa  dòng  thì  kích  thước  dữ  liệu  ra  =  kích  thước  dữ  liệu  vào.   •  Với  các  giải  thuật  mã  hóa  khối  thì  kích  thước  dữ  liệu  ra  <=    kích  thước  dữ  liệu  vào   +  kích  thước  khối.   •  Hàm  CryptEncrypt  sẽ  ghi  đè  dữ  liệu  mã  hóa  được  vào  bộ  đệm  chứa  dữ  liệu  vào.   •  Đoạn  chương  trình  thực  hiện  mã  hóa  chung  cho  cả  hai  loại.   4.6  Microsoft  Crypto  API   76   ALG_ID  Algid;      //  Giải  thuật  mã   char  *  pbData  =  "Hello  CryptAPI";    //  Xâu  nguồn  cần  mã   char  *  pbResult  =  0;    //  Xâu  kết  quả   DWORD  dwDataLen  =  0,dwBlockLen  =  0;    cbData  =  strlen(pbData);  //  Chiều  dài  xâu  nguồn      dwDataLen  =  sizeof(ALG_ID);   //  Lấy  thông  tin  về  giải  thuật  mã  hóa  với  key  cho  trước      if  (!CryptGetKeyParam(hKey,  KP_ALGID,  (BYTE  *)&Algid,  &dwDataLen,  0))      return  0;     •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Mã  hóa  với  CryptEncrypt     4.6  Microsoft  Crypto  API   77   if  (GET_ALG_TYPE(Algid)  !=  ALG_TYPE_STREAM)    //  Mã  hóa  khối      {            dwDataLen  =  sizeof(DWORD);                ret  =  CryptGetKeyParam(hKey,    KP_BLOCKLEN,  (BYTE*)&dwBlockLen,          &dwDataLen,  0);  //  Lấy  kích  thước  block  theo  bit    dwBlockLen  =  dwBlockLen/8;  //  Đổi  kích  thước  block  ra  đơn  vị  byte      //  Cấp  phát  bộ  nhớ  để  chứa  kết  quả        pbResult  =  (char*)malloc(cbData+dwBlockLen);    memcpy(pbResult,pbData,cbData);    //  Thực  hiện  mã  hóa,  kết  quả  là  dwDataLen  byte  lưu  trong  pbResult    dwDataLen  =  cbData;      CryptEncrypt(hKey,  0,  TRUE,  0,  (BYTE*)pbResult,  &dwDataLen,          cbData+16))  ;   }   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Mã  hóa  với  CryptEncrypt  (tiếp)     4.6  Microsoft  Crypto  API   78   else  //  Mã  hóa  dòng   {    //  Cấp  phát  bộ  nhớ  lưu  kết  quả    pbResult  =  (char*)malloc(cbData);    //  Bảo  toàn  dữ  liệu  nguồn    memcpy(pbResult,pbData,cbData);    //  Thực  hiện  mã  hóa    CryptEncrypt(hKey,0,TRUE,0,pbResult,&dwDataLen,cbData);   }   •  Sử  dụng  thư  viện  CryptoAPI  để  thực  hiện  mã  hóa  đối  xứng  thông  điệp  với  thuật  toán  AES.   •  Giải  mã  với  CryptDecrypt   •  Kích  thước  dữ  liệu  đích  <=  kích  thước  dữ  liệu  nguồn   •  Thực  hiện  đơn  giản  hơn  so  với  CryptEncrypt   •  Ví  dụ     4.6  Microsoft  Crypto  API   79   char  *  pbData  ;      //  Dữ  liệu  nguồn   DWORD  cbData;    //  Kích  thước  nguồn   char  *  pbResult;      //  Dữ  liệu  đích   DWORD  dwDataLen;  //  Kích  thước  đích   //  Cấp  phát  bộ  nhớ  và  sao  chép  dữ  liệu  nguồn  vào  đích   pbResult  =  (char*)malloc(cbData);   memcpy(pbResult,  pbData,  cbData);   dwDataLen  =  cbDataLen;   //  Giải  mã,  kết  quả  là  dwDataLen  byte  lưu  trong  pbResult   CryptDecrypt(hKey,0,TRUE,0,pbResult,&dwDataLen);   •  Trao  đổi  khóa  với  OpenSSL   •  CryptoAPI  không  cho  phép  nhập  và  xuất  khóa  dạng  thô  như  OpenSSL.   •  Để  trao  đổi  khóa  với  thư  viện  khác,  cần  mã  hóa  khóa  theo  giải  thuật  AT_KEYEXCHANGE,  và  thực  hiện  nhập  xuất  dưới  dạng  cấu  trúc  BLOB.   •  Hàm  CryptImportKeyvà  CryptExportKey  dùng  để  thực  hiện  nhập  xuất  khóa.   •  Xem  thêm  phần  5.26,  5.27  trong  Secure  Programming  Cookbook.     4.6  Microsoft  Crypto  API   80   Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  5.  Hàm  băm  và  xác  thực   thông  điệp   Hashes  and  Message  Authentication   5.1  Các  loại  hàm  băm  và  MAC  thông  dụng  5.2  Băm  với  OpenSSL    5.3  Băm  dữ  liệu  với  CryptoAPI    5.4  Xác  thực  thông  điệp  với  HMAC  5.5  Salt   Nội  dung   82   •  Hàm  băm  (hashes)  –  Nhận  đầu  vào  là  một  xâu  và  đầu  ra  là  một  chuỗi  bit  có  chiều  dài  xác  định.  –  Tỉ  lệ  đụng  độ  rất  nhỏ.    –  Dùng  để  kiểm  tra  tính  toàn  vẹn  của  dữ  liệu  nhưng  không  đảm  bảo  tính  xác  thực  của  dữ  liệu.  –  Thường  kết  hợp  với  mô  hình  mã  hóa  công  khai  chứ  không  sử  dụng  một  mình.  –  Các  giải  thuật  băm  thông  dụng:  MD5,  SHA1   5.1  Các  hàm  băm  và  MAC  thông  dụng   83   •  Hàm  băm  (hashes)  5.1  Các  hàm  băm  và  MAC  thông  dụng   84   Algorithm   Digest  size   Security  conqidence   Small  message   speed  (64  bytes),  in   cycles  per  byte[2]   Large  message   speed  (8K),  in   cycles  per  byte   Uses  block  cipher   Davies-­‐Meyer-­‐ AES-­‐128   128  bits  (same  length  as  cipher  block  size)   Good   46.7  cpb   57.8  cpb   Yes   MD2   128  bits   Good  to  low   392  cpb   184  cpb   No   MD4   128  bits   Insecure   32  cpb   5.8  cpb   No   MD5   128  bits   Very  low,  may  be  insecure   40.9  cpb   7.7  cpb   No   MDC-­‐2-­‐AES-­‐128   256  bits   Very  high   93  cpb   116  cpb   Yes   MDC-­‐2-­‐DES   128  bits   Good   444  cpb   444  cpb   Yes   RIPEMD-­‐160   160  bits   High   62.2  cpb   20.6  cpb   No   SHA1   160  bits   High   53  cpb   15.9  cpb   No   SHA-­‐256   256  bits   Very  high   119  cpb   116  cpb   No   SHA-­‐384   384  bits   Very  high   171  cpb   166  cpb   No   SHA-­‐512   512  bits   Very  high   171  cpb   166  cpb   No   •  Xác  thực  thông  điệp  (Message  Authentication  Code)  –  Nhận  đầu  vào  là  một  xâu  và  một  khóa  bí  mật,  đầu  ra  là  một  mã  có  chiều  dài  xác  định.  –  Dùng  để  kiểm  tra  tính  toàn  vẹn  và  xác  thực  của  dữ  liệu.  –  Các  giải  thuật  thông  dụng:  OMAC,  CMAC,  HMAC   5.1  Các  hàm  băm  và  MAC  thông  dụng   85   •  Xác  thực  thông  điệp  (Message  Authentication  Code)  5.1  Các  hàm  băm  và  MAC  thông  dụng   86   MAC   Built  upon   Small  message   speed  (64   bytes)[4]   Large  message   speed  (8K)   Appropriate   for  hardware   Patent  restric-­‐ tions   Parallel-­‐izable   CMAC   A  universal  hash  and  AES   ~18  cpb   ~18  cpb   Yes   No   Yes   HMAC-­‐SHA1   Message  digest  function   90  cpb   20  cpb   Yes   No   No   MAC127   hash127  +  AES   ~6  cpb   ~6  cpb   Yes   No   Yes   OMAC1   AES   29.5  cpb   37  cpb   Yes   No   No   OMAC2   AES   29.5  cpb   37  cpb   Yes   No   No   PMAC-­‐AES   Block  cipher   72  cpb   70  cpb   Yes   Yes   Yes   RMAC   Block  cipher   89  cpb   80  cpb   Yes   No   No   UMAC32   UHASH  and  AES   19  cpb   cpb   No   No   Yes   XMACC-­‐SHA1   Any  cipher  or  MD  function   162  cpb   29  cpb   Yes   Yes   Yes   •  OpenSSL  cung  cấp  hai  loại  giao  diện  với  các  hàm  băm  –  Giao  diện  riêng  rẽ  với  mỗi  giải  thuật  băm  cụ  thể.  •  Mỗi  giải  thuật  băm  có  tệp  tiêu  đề  riêng  •  Tên  gọi  các  hàm  là  khác  nhau  cho  các  giải  thuật  băm.  –  Giao  diện  chung  EVP  cho  mọi  loại  hàm  băm.  •  Tệp  tiêu  đề  chung:    •  Trình  tự  sử  dụng  như  nhau:  –  Khởi  tạo  ngữ  cảnh:  EVP_DigestInit  –  Cập  nhật  dữ  liệu  băm:  EVP_DigestUpdate  –  Lấy  kết  quả:  EVP_DigestFinal.   5.2  Băm  dữ  liệu  với  OpenSSL   87   •  VD:  Băm  với  SHA1  5.2  Băm  dữ  liệu  với  OpenSSL   88    #include      int                      i;    SHA_CTX              ctx;          unsigned  char  result[SHA_DIGEST_LENGTH];    /*  SHA1  has  a  20-­‐byte  digest.  */      unsigned  char  *s1  =  (unsigned  char*)"Testing";          unsigned  char  *s2  =  (unsigned  char*)"...1...2...3...";              SHA1_Init(&ctx);          SHA1_Update(&ctx,  s1,  strlen((char*)s1));      SHA1_Update(&ctx,  s2,  strlen((char*)s2));      /*  Yes,  the  context  object  is  last.  */      SHA1_Final(result,  &ctx);      printf("SHA1(\"%s%s\")  =  ",  s1,  s2);          for  (i  =  0;    i  <  SHA_DIGEST_LENGTH;    i++)  printf("%02x",  result[i]);      printf("\n");   •  VD:  Băm  với  giao  diện  EVP  5.2  Băm  dữ  liệu  với  OpenSSL   89   #include    #include    #include        int                      i  ,  ol;      EVP_MD_CTX        ctx;      unsigned  char  *result;      unsigned  char  *s1  =  (unsigned  char*)"Testing";      unsigned  char  *s2  =  (unsigned  char*)"...1...2...3...";      EVP_DigestInit(&ctx,  EVP_sha1());      EVP_DigestUpdate(&ctx,  s1,  strlen((char*)s1));      EVP_DigestUpdate(&ctx,  s2,  strlen((char*)s2));      if  (!(result  =  (unsigned  char  *)malloc(EVP_MD_CTX_block_size(&ctx))))abort();      EVP_DigestFinal(&ctx,  result,  &ol);      printf("SHA1(\"%s%s\")  =  ",  s1,  s2);      for  (i  =  0;    i  <  ol;    i++)  printf("%02x",  result[i]);      printf("\n");        free(result);   •  Trình  tự  băm  với  CryptoAPI  –  Tệp  tiêu  đề:  Wincrypt.h  –  Khởi  tạo  ngữ  cảnh  Provider:  CryptAcquireContext  –  Tạo  đối  tượng  hash:  CryptCreateHash  –  Băm  liên  tiếp  với:  CryptHashData  –  Lấy  kết  quả:  CryptGetHashParam  –  Giải  phóng  đói  tượng  hash:  CryptDestroyHash   5.3  Băm  dữ  liệu  với  CryptoAPI   90   •  Ví  dụ:  Băm  dữ  liệu  với  thuật  toán  SHA-­‐256  5.3  Băm  dữ  liệu  với  CryptoAPI   91      BYTE                    *pbData;      DWORD                  cbData  =  sizeof(DWORD),  cbHashSize,  i;      HCRYPTHASH        hSHA256;      HCRYPTPROV        hProvider;      unsigned  char  *s1  =  (unsigned  char*)"Testing";      unsigned  char  *s2  =  (unsigned  char*)"...1...2...3...";      //  Khởi  tạo  ngữ  cảnh  Provider      CryptAcquireContext(&hProvider,  0,  MS_ENH_RSA_AES_PROV,  PROV_RSA_AES,  0);      //  Tạo  đối  tượng  hàm  băm      CryptCreateHash(hProvider,  CALG_SHA_256,  0,  0,  &hSHA256);      //  Thực  hiện  băm      CryptHashData(hSHA256,  s1,  strlen((char*)s1),  0);      CryptHashData(hSHA256,  s2,  strlen((char*)s2),  0);    //  Thực  hiện  băm         •  Ví  dụ:  Băm  dữ  liệu  với  thuật  toán  SHA-­‐256  (tiếp)  5.3  Băm  dữ  liệu  với  CryptoAPI   92      //  Lấy  kích  thước  dữ  liệu  băm  được      CryptGetHashParam(hSHA256,  HP_HASHSIZE,  (BYTE  *)&cbHashSize,  &cbData,  0);      pbData  =  (BYTE  *)LocalAlloc(LMEM_FIXED,  cbHashSize);      //  Lấy  dữ  liệu  băm  được      CryptGetHashParam(hSHA256,  HP_HASHVAL,  pbData,  &cbHashSize,  0);      //  Giải  phóng  đối  tượng  băm  và  ngữ  cảnh  Provider      CryptDestroyHash(hSHA256);      CryptReleaseContext(hProvider,  0);              printf("SHA256(\"%s%s\")  =  ",  s1,  s2);      for  (i  =  0;    i  <  cbHashSize;    i++)  printf("%02x",  pbData[i]);      printf("\n");              LocalFree(pbData);             •  Với  OpenSSL  –  Tệp  tiêu  đều    –  Gọi  hàm  HMAC_Init  để  khởi  tạo  ngữ  cảnh  và  key  sẽ  sử  dụng  –  Liên  tục  gọi  hàm  HMAC_Update  để  cập  nhật  dữ  liệu.  –  Gọi  hàm  HMAC_Final  để  kết  thúc  quá  trình  băm  –  Gọi  hàm  HMAC_cleanup  để  xóa  key  khỏi  bộ  nhớ.  –  Có  thể  gọi  hàm  All-­‐in-­‐one  HMAC  –  Bên  nhận  kiểm  tra  lại  bằng  cách  thực  hiện  băm  với  với  cùng  một  key  và  giải  thuật  và  so  sánh  kết  quả   5.4  Xác  thực  thông  điệp  với  HMAC   93   •  Với  OpenSSL  5.4  Xác  thực  thông  điệp  với  HMAC   94      int                      i;      HMAC_CTX            ctx;      unsigned  int    len;      unsigned  char  out[20];      unsigned  char  *  key  =  (unsigned  char*)"secret";      int      keylen  =  strlen((char*)key);      //  Khởi  tạo  HMAC  với  key  là  secret      HMAC_Init(&ctx,  key,  keylen,  EVP_sha1(    ));      //  Thực  hiện  băm  xâu  "fr      HMAC_Update(&ctx,  (unsigned  char*)"hash  me  pls",  11);      //  Lấy  kết  quả      HMAC_Final(&ctx,  out,  &len);      for  (i  =  0;    i  <  len;    i++)  printf("%02x",  out[i]);      printf("\n");   •  Với  CryptAPI  –  Tạo  đối  tượng  Hash  với  hàm  CryptCreateHash,  trong  đó  tham  số  hKey  là  một  key  đã  được  tạo  trước.  –  Thiết  lập  thông  tin  về  giải  thuật  băm  với  hàm  CryptSetHashParam.  –  Thực  hiện  băm  với  hàm  CryptHashData  –  Lấy  kích  thước,  nội  của  dữ  liệu  băm  được  với  hàm  CryptGetHashParam.  –  Giải  phóng  đói  tượng  Hash  và  Key     5.4  Xác  thực  thông  điệp  với  HMAC   95   •  Với  CryptAPI     5.4  Xác  thực  thông  điệp  với  HMAC   96      BYTE              out[20];      DWORD            cbData  =  sizeof(out),  i;      HCRYPTKEY    hKey;      HMAC_INFO    HMACInfo;      HCRYPTHASH  hHash;      HCRYPTPROV  hProvider;      //  Lấy  ngữ  cảnh  provider    CryptAcquireContext(&hProvider,0,MS_ENH_RSA_AES_PROV,PROV_RSA_AES,CRYPT_VERIFYCONTEXT);      //  Sinh  key  từ  mật  khẩu                  hKey  =  CreateKeyFromPassword(hProvider,"secret");      //  Tạo  đối  tượng  băm      CryptCreateHash(hProvider,  CALG_HMAC,  hKey,  0,  &hHash);         •  Với  CryptAPI     5.4  Xác  thực  thông  điệp  với  HMAC   97   //  Thiết  lập  giải  thuật  băm      HMACInfo.HashAlgid          =  CALG_SHA1;      HMACInfo.pbInnerString  =  HMACInfo.pbOuterString  =  0;      HMACInfo.cbInnerString  =  HMACInfo.cbOuterString  =  0;      CryptSetHashParam(hHash,  HP_HMAC_INFO,  (BYTE  *)&HMACInfo,  0);      //  Thực  hiện  băm        CryptHashData(hHash,  (BYTE  *)"Hash  me  plz",  11,  0);      //  Lấy  kết  quả      CryptGetHashParam(hHash,  HP_HASHVAL,  out,  &cbData,  0);      for  (i  =  0;    i  <  cbData;    i++)  printf("%02x",  out[i]);      printf("\n");              CryptDestroyHash(hHash);      CryptDestroyKey(hKey);      CryptReleaseContext(hProvider,  0);         •  Salt  –  Chuỗi  dữ  liệu  thêm  vào  để  tăng  không  gian  khóa  và  chống  lại  hình  thức  replay-­‐attack.  –  Hai  bên  có  thể  thỏa  thuận  chung  một  salt  nào  đó  thay  đổi  theo  thời  gian.  –  Salt  thường  được  thêm  vào  đầu  thông  điệp  gốc,  sau  đó  thực  hiện  băm  cả  salt  cả  thông  điệp.     5.5  Sử  dụng  Salt   98   1.  Viết  chương  trình  mã  hóa  và  giải  mã  tệp  tin  bằng  giải  thuật  AES-­‐256  bit.  Mật  khẩu  nhập  từ  bàn  phím.  Kiểm  tra  tính  đúng  đắn  của  kết  quả  bằng  giải  thuật  SHA-­‐256.  Sử  dụng  thư  viện  OpenSSL.  Khuôn  dạng  dữ  liệu  của  tệp  tin  sau  khi  mã  hóa  có  thể  như  sau:        2.  Viết  chương  trình  chat  client-­‐server  đơn  giản  trong  đó  kênh  truyền  được  mã  hóa  theo  giải  thuật  AES-­‐256.  Key  được  sinh  ra  từ  mật  khẩu  thỏa  thuận  trước  và  không  truyền  qua  mạng,  Vector  khởi  tạo  là  mã  BCD  được  thiết  lập  từ  ngày  và  giờ  hiện  tại  của  hệ  thống  (Hàm  API  GetSystemTime).  Ví  dụ:  Nếu  hiện  tại  là  07h  ngày  10/10/2011  thì  giá  trị  dưới  dạng  hexa  của  vector  khởi  tạo  là   2011101007000.00     Bài  tập   99   3.  Viết  chương  trình  băm  nội  dung  một  }ile  bằng  giải  thuật  HMAC-­‐AES256,  sử  dụng  thư  viện  OpenSSL.  Mật  khẩu  để  băm  nhập  từ  bàn  phím.Kết  quả  băm  được  lưu  vào  cuối  }ile.  4.  Viết  chương  trình  kiểm  tra  tính  toàn  vẹn  của  một  }ile  bằng  giải  thuật  HMAC-­‐AES256.  Mật  khẩu  để  kiểm  tra  nhập  từ  bàn  phím.     Bài  tập   100   Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  6.  Mã  hóa  công  khai   Public  Key  Cryptography   6.1  Mã  hóa  với  OpenSSL  RSA  6.2  Chữ  ký  số  6.3  Biểu  diễn  khóa  6.4  Kết  nối  SSL  6.5  Hạ  tầng  khóa  công  khai     Nội  dung   102   •  Mã  hóa  bất  đối  xứng   •  Là  các  giải  thuật  sử  dụng  một  cặp  khóa  cho  việc  mã  hóa  và  giải  mã   •  Dữ  liệu  được  mã  hóa  bằng  khóa  công  khai  sẽ  được  giải  mã  bằng  khóa  bí  mật  và  ngược  lại.   •  Các  giải  thuật  thông  dụng:  RSA,  DSA,  Dif}ie-­‐Hellman.   •  Không  sử  dụng  trực  tiếp  để  mã  hóa  dữ  liệu  vì  tốc  độ  rất  chậm.   •  Thường  được  sử  dụng  để   •  Trao  đổi  khóa  đối  xứng  trong  phiên  truyền  mật   •  Chữ  ký  số   •  Xác  nhận  danh  tính   •    6.1  Mã  hóa  với  OpenSSL  RSA     103   •  OpenSSL  RSA   •  Thường  được  sử  dụng  trao  đổi  khóa   •  Lưu  trữ  tất  cả  thông  tin  về  một  khóa  dưới  cấu  trúc  RSA.   •  Tệp  tiêu  đề  rsa.h   •  Sinh  cặp  khóa  đối  xứng  bằng  hàm      RSA  *RSA_generate_key(int  bits,      //  Kích  thước  khóa:  1024,2048        unsigned  long  exp,//  Số  mũ:  3,  17,  65537          void  (*cb)(int,  int,  void),    //  Callback        void  *cb_arg);       6.1  Mã  hóa  với  OpenSSL  RSA     104   •  Mã  hóa  với  khóa  công  khai   •  Sử  dụng  hàm  RSA_public_encrypt:    int  RSA_public_encrypt(int  l,  //  Chiều  dài  dữ  liệu          unsigned  char  *pt,  //  Xâu/số  cần  mã        unsigned  char  *ct,  //  Kết  quả        RSA  *r,            //  Cấu  trúc  RSA          int  p);          //  Kiểu  padding    Kết  quả  trả  về:  chiều  dài  xâu  mã  được.     6.1  Mã  hóa  với  OpenSSL  RSA     105   •  Giải  mã  với  khóa  bí  mật   •  Sử  dụng  hàm  RSA_private_decrypt:    int  RSA_private_decrypt(int  l,            unsigned  char  *ct,          unsigned  char  *pt,          RSA  *r,          int  p);    Kết  quả  trả  về:  chiều  dài  xâu  giải  mã  được   6.1  Mã  hóa  với  OpenSSL  RSA     106   •  Bài  tập  –  Viết  chương  trình  chat  console  client-­‐server  sử  dụng  giải  thuật  RSA.  Chỉ  chia  sẻ  public  key  trên  đường  truyền.   6.1  Mã  hóa  với  OpenSSL  RSA     107   •  Chữ  ký  số  dữ  liệu  nhằm  xác  thực  danh  tính  của  người  gửi,  tương  tự  như  HMAC  nhưng  sử  dụng  giải  thuật  RSA  •  Quá  trình  ký  số  dữ  liệu  nhận  đầu  vào  là  giá  trị  băm  của  thông  điệp,  khóa  bí  mật  của  người  gửi,  đầu  ra  là  giá  trị  hàm  băm  đã  được  mã  hóa.  •  Bên  nhận  thực  hiện  quá  trình  ngược  lại:  tính  giá  trị  băm  của  thông  điệp,  giải  mã  giá  trị  băm  đã  mã  hóa  của  bên  gửi  bằng  khóa  công  khai  và  so  sánh  hai  giá  trị  băm  này.  •  Hacker  không  thể  giả  mạo  giá  trị  băm  vì  không  có  khóa  bí  mật  của  bên  gửi.   6.2  Chữ  ký  số     108   •  Sơ  đồ  ký   6.2  Chữ  ký  số     109   Dữ  liệu   Giá  trị  băm   (MD)   H as h   (S H A1 )   Chữ  ký   Khóa  bí  mật   Mã  hóa   Dữ  liệu  +  Chữ   ký   •  Thực  hiện  bằng  OpenSSL  RSA  –  Hàm  RSA_sign  là  hàm  mức  thấp    của  OpenSSL  thực  hiện  ký  số  dữ  liệu   6.2  Chữ  ký  số     110   int  RSA_sign(int  md_type,    //  Loại  Message  Digest:  SHA1,  MD5    unsigned  char  *dgst,  //  Bản  thân  dữ  liệu  (Message  Digest)    unsigned  int  dlen,            //  Kích  thước    unsigned  char  *sig,        //  Chữ  ký    unsigned  int  *siglen,    //  Chiều  dài  chữ  ký    RSA  *r);                                                      //  Khóa  bí  mật     •  Thực  hiện  bằng  OpenSSL  RSA  –  Hàm  RSA_verify  thực  hiện  công  việc  ngược  lại:  kiểm  tra  tính  hợp  lệ  của  chữ  ký   •  Thực  hiện  bằng  OpenSSL  DSA  –  Xem  thêm  trong  sách  (phần  7.15)   6.2  Chữ  ký  số     111   int  RSA_verify(int  md_type,    //Loại  message  digest:  md5,sha1,      unsigned  char  *dgst,  //  message  digest    unsigned  int  dlen,            //  kích  thước  message  digest    unsigned  char  *sig,        //  Chữ  ký    unsigned  int  siglen,        //  Chiều  dài  chữ  ký    RSA  *r);                                                    //  Khóa  công  khai   •  Biểu  diễn  khóa  và  chứng  thực  –  DER  (Binary)  –  PEM  (Plaintext)  •  Biểu  diễn  DER  –  Chuẩn  quốc  tế  thông  dụng    –  Các  hàm  OpenSSL  tương  ứng:  i2d  và  d2i  (internal  representation  ó  DER)  –  Ví  dụ  chuyển  khóa  công  khai  RSA  sang  lưu  trữ  dưới  dạng  DER     6.3  Biểu  diễn  khóa   112   unsigned  char  *DER_encode_RSA_public(RSA  *rsa,  int  *len)    {      unsigned  char  *buf,  *next;      *len  =  i2d_RSAPublicKey(rsa,  0);      if  (!(buf  =  next  =  (unsigned  char  *)malloc(*len)))  return  0;    i2d_RSAPublicKey(rsa,  &next);      /*  If  we  use  buf  here,  return  buf;  becomes  wrong  */      return  buf;    }   •  Biểu  diễn  DER  –  Ví  dụ  chuyển  khóa  từ  dạng  DER  sang  dạng  khóa  công  khai  RSA     6.3  Biểu  diễn  khóa  công  khai     113   RSA  *DER_decode_RSA_public(unsigned  char  *buf,  long  len)    {      return  d2i_RSAPublicKey(0,  &buf,  len);    }   •  Biểu  diễn  PEM  (Privacy  Enhanced  Mail)  –  Thực  chất  là  biểu  diễn  DER  dưới  dạng  Base64  và  có  thêm  phần  header,  footer  và  có  thể  mã  hóa  –  Ví  dụ  -­‐-­‐-­‐-­‐-­‐BEGIN  RSA  PRIVATE  KEY-­‐-­‐-­‐-­‐-­‐    Proc-­‐Type:  4,ENCRYPTED    DEK-­‐Info:  DES-­‐EDE3-­‐CBC,F2D4E6438DBD4EA8    LjKQ2r1Yt9foxbHdLKZeClqZuzN7PoEmy+b+dKq9qibaH4pRcwATuWt4/Jzl6y85  NHM6CM4bOV1MHkyD01tFsT4kJ0GwRPg4tKAiTNjE4Yrz9V3rESiQKridtXMOToEp  Mj2nSvVKRSNEeG33GNIYUeMfSSc3oTmZVOlHNp9f8LEYWNmIjfzlHExvgJaPrixX  QiPGJ6K05kV5FJWRPET9vI+kyouAm6DBcyAhmR80NYRvaBbXGM/MxBgQ7koFVaI5  zoJ/NBdEIMdHNUh0h11GQCXAQXOSL6Fx2hRdcicm6j1CPd3AFrTt9EATmd4Hj+D4  91jDYXElALfdSbiO0A9Mz6USUepTXwlfVV/cbBpLRz5Rqnyg2EwI2tZRU+E+Cusb  /b6hcuWyzva895YMUCSyDaLgSsIqRWmXxQV1W2bAgRbs8jD8VF+G9w==    -­‐-­‐-­‐-­‐-­‐END  RSA  PRIVATE  KEY-­‐-­‐-­‐-­‐-­‐   6.3  Biểu  diễn  khóa  công  khai     114   •  Biểu  diễn  PEM  (Privacy  Enhanced  Mail)  –  Các  hàm  OpenSSL:  •  Tệp  tiêu  đề      •  PEM_read_***  •  PEM_write_***  –  Ví  dụ  ghi  ra  bộ  nhớ  khóa  bí  mật  RSA  được  mã  hóa  dưới  dạng  PEM  –  AES256-­‐CBC   6.3  Biểu  diễn  khóa  công  khai     115   #include     #include     int  password_cb(char  *buf,  int  len,  int  rwqlag,  void  *cb_arg)   {    strcpy(buf,"hello");    return  strlen(buf);   }   BIO  *  mem  =  BIO_new(BIO_s_mem());   BUF_MEM  *  bp;   BIO_get_mem_ptr(mem,&bp);   PEM_write_bio_RSAPrivateKey(mem,key,EVP_aes_256_cbc(),          0,0,password_cb,0);   •  Secure  Socket  Layer  (SSL)  là  giao  thức  ở  tầng  ứng  dụng  cung  cấp  dịch  vụ  kết  nối  an  toàn  giữa  hai  ứng  dụng  trên  cơ  sở  hạ  tầng  khóa  công  khai.  •  OpenSSL  cung  cấp  SSL  API  để  có  thể  viết  ứng  dụng  SSL  nhanh  chóng.  •  ­‐openssl/index.html#ibm-­‐pcon  •  OpenSSL  common  commands  –  NSA  Cyber  Security   6.4  Kết  nối  SSL   116   •  Sử  dụng  bên  thứ  ba  để  chứng  thực  danh  tính  các  bên.  •  Chống  được  hình  thức  tấn  công  Man-­‐In-­‐The  Middle  •  Một  số  lệnh  thông  dụng  với  OpenSSL  –  ­‐howtos/usefulopenssl.html   6.5  Hạ  tầng  khóa  công  khai     117   Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  7.  Anti-­‐Tampering   7.1  Phát  hiện  thay  đổi  (Detecting  modi}ication)  7.2  Che  giấu  mã  (Code  hiding)  7.3  Sử  dụng  con  trỏ  hàm  (Function  Pointer)  7.4  Giấu  xâu  (String  hiding)  7.5  Phát  hiện  debugger  (Anti-­‐Debugger)  7.6  Self-­‐modifying  code  7.7  Giải  pháp  tổng  thể     Nội  dung   119   •  Mục  tiêu:  Phát  hiện  chương  trình  đã  bị  crack  chưa  (Detecting  modi}ication)  •  Kỹ  thuật:  –  Tính  MD5,  SHA1,  hoặc  HMAC  mã  lệnh  của  }ile  thực  thi.  –  Đánh  dấu  một  đoạn  trong  chương  trình  sẽ  dùng  để  lưu  mã  băm  }ile  thực  thi  và  ghi  giá  trị  băm  vào  đó  bằng  một  chương  trình  Hex  edit  khác.  –  Tại  thời  điểm  runtime  tính  lại  giá  trị  băm  của  }ile  thực  thi  và  so  sánh  với  mã  băm  trước  đó.  •  Ví  dụ:         7.1  Phát  hiện  thay  đổi  mã  lệnh   120   //  Khai  báo  xâu  đánh  dấu  mã  băm  char  *  md5hash  =  "AAAAXXXXXXXXXXXXXXXX";  int  _tmain(int  argc,  _TCHAR*  argv[])  {    unsigned  char  hash[16];//  Giá  trị  băm  tính  được    unsigned  char  expectedhash[16];//  Giá  trị  băm  lưu  trong  }ile        FILE  *  fp  =  fopen(argv[0],"rb");//  Mở  }ile  để  tính  lại  giá  trị  băm    unsigned  char  *  pFile  ;    fseek(fp,0,SEEK_END);    int  len  =  ftell(fp);   •  Ví  dụ:         7.1  Phát  hiện  thay  đổi  mã  lệnh   121   pFile  =  (unsigned  char*)malloc(len);  fseek(fp,0,SEEK_SET);  fread(pFile,1,len,fp);  md5hash  =  0;  for  (int  i=0;i<len-­‐20;i++)  //  Dò  tìm  giá  trị  băm  trong  }ile    if  ((pFile[i]=='A')&&(pFile[i+1]=='A')&&        (pFile[i+2]=='A')&&(pFile[i+3]=='A'))    {    memcpy(expectedhash,pFile+i+4,16);  //  Lưu  ra  mảng  khác    memset(pFile+i+4,0,16);    //  Xóa  trắng  giá  trị  này  trong  }ile    }  MD5(pFile,len,hash);        //  Tính  lại  giá  trị  băm      printf("File  hash:");    print_md5(hash);              printf("Expected  hash:");    print_md5(expectedhash);    if  (memcmp(hash,expectedhash,16))    {      printf("File  veri}ication  failed");    }    getch();    return  0;  }   •  Hạn  chế  –  Dễ  bị  đánh  bại  nếu  sử  dụng  hash  vì  cracker  cũng  có  thể  tính  lại  giá  trị  băm  và  sửa  }ile  cho  chính  xác.  –  Nếu  sử  dụng  HMAC  thì  phải  lưu  mật  khẩu  ở  đâu  đó  •  Lưu  trong  }ile:  Cũng  sẽ  bị  cracker  dò  ra  •  Lưu  trên  internet:  cần  có  kết  nối  internet  và  dễ  dàng  bị  dò  ra  nếu  dùng  sniffer.  •  CURL         7.1  Phát  hiện  thay  đổi  mã  lệnh   122   •  Mục  tiêu  –  Gây  khó  khăn  cho  quá  trình  dịch  ngược  và  phân  tích  bằng  các  disassembler  (Obfuscating  code).  Windasm,  OllyDbg,  IDA  –  Che  giấu  các  cấu  trúc  điều  khiển  quan  trọng  trong  chương  trình.  •  Cấu  trúc  điều  kiện  •  Cấu  trúc  lặp  •  Kỹ  thuật    –  Cần  sự  hỗ  trợ  của  trình  biên  dịch  –  Thực  hiện  ở  mức  hợp  ngữ  –  Sử  dụng  các  điều  kiện  so  sánh  “bất  thường”  •  So  sánh  khác  thay  vì  bằng  •  Vòng  lặp  giảm  thay  vì  tăng.  •  Vòng  lặp  có  chỉ  số  tăng  khác  1.  •              7.2  Che  giấu  mã   123   •  Mục  tiêu  –  Gây  khó  khăn  cho  các  công  cụ  disassembler  trong  việc  phân  tích  lời  gọi  hàm  •  Kỹ  thuật    –  Không  thực  hiện  lời  gọi  hàm  trực  tiếp  trong  chương  trình  mà  sử  dụng  các  con  trỏ  hàm.  –  VD             7.3  Sử  dụng  con  trỏ  hàm   124   void  my_func()  {  }  typedef  void  (*FUNC)();  int  _tmain(int  argc,  _TCHAR*  argv[])  {    FUNC  ptr;    ptr  =  my_func;    printf("ptr  address:%p",ptr);    ptr();                                            /*  make  the  function  call  */    return  0;  }     •  Mục  tiêu  –  Gây  khó  khăn  cho  các  công  cụ  disassembler  trong  việc  phân  tích  các  xâu  nhạy  cảm  trong  chương  trình.VD  •  Invalid  cd-­‐key  •  Registration  successful  •   •  Kỹ  thuật    –  Mã  hóa  các  xâu  trong  chương  trình    •  Base64  •  RC4  •  Giải  thuật  tự  chọn  •              7.4  Giấu  xâu   125   •  Ví  dụ:  dịch  mã  các  ký  tự  trong  xâu  đi  0x19     7.4  Giấu  xâu   126   #include    #de}ine  A(c)                        (c)  -­‐  0x19  #de}ine  UNHIDE_STR(str)  do  {  char  *p  =  str;    while  (*p)  *p++  +=  0x19;  }  while  (0)  #de}ine  HIDE_STR(str)      do  {  char  *p  =  str;    while  (*p)  *p++  -­‐=  0x19;  }  while  (0)    int  main(int  argc,  char  *argv[    ])  {  char  str[    ]  =  {          A('/'),  A('e'),  A('t'),  A('c'),  A('/'),          A('p'),  A('a'),  A('s'),  A('s'),  A('w'),  A('d'),  0      };              UNHIDE_STR(str);      printf("%s\n",  str);      HIDE_STR(str);              return  0;  }   •  Mục  đích:  Phát  hiện  sự  tồn  tại  của  debugger  •  Kỹ  thuật:  rất  nhiều  (google  :  anti-­‐debugger)  –  Kernel32!IsDebuggerPresent  –  PEB!IsDebugged  –  PEB!NtGlobalFlags  –  Self-­‐debugging  –  .  •  Ví  dụ     7.5  Phát  hiện  debugger   127   #include    int  _tmain(int  argc,  _TCHAR*  argv[])  {    if(IsDebuggerPresent())    {      printf("Program  is  being  debugged");    }    return  0;  }   •  Mục  đích:  –  Mã  hóa  lệnh  quan  trọng,  chỉ  giải  mã  khi  cần  thực  hiện  •  Kỹ  thuật  –  Không  có  sự  trợ  giúp  của  trình  biên  dịch.  –  Gần  như  không  thể  thực  hiện  bằng  C/C++  –  Cần  hiểu  rất  sâu  về  hệ  điều  hành  +  hợp  ngữ  –  Googe:  shellcode  •  Ưu  điểm  –  Không  thể  dissassembler  nếu  chưa  giải  mã.  –  Không  dành  cho  amater  cracker.  •  Nhược  điểm  –  Rất  khó  bảo  trì  –  Vẫn  có  thể  crack  được  nếu  đặt  đúng  breakpoint  tại  điểm  decrypt  –  Xung  đột  với  DEP  (Data  Execution  Preventation)   7.6  Self-­‐modifying  code   128   •  Các  kỹ  thuật  trên  nếu  kết  hợp  lại  có  thể  có  kết  quả  rất  tốt.  •  Trên  Windows:  –  Sử  dụng  các  chương  trình  all-­‐in-­‐one:  “Packer”  •  ASPack  •  ASProtect  •  PECompact  •  PECrypt  •  Themida  •   –  Code-­‐sign  ứng  dụng  bằng  chữ  ký  số  ­‐us/library/ms537361%28v=vs.85%29.aspx  •  Trên  các  hệ  điều  hành  khác  –  Đang  tiến  dần  đến  xu  hướng  code-­‐sign:  VD  iOS,  MacOS   7.7  Giải  pháp  tổng  thể   129   •  Các  kỹ  thuật  trên  nếu  kết  hợp  lại  có  thể  có  kết  quả  rất  tốt.  •  Trên  Windows:  –  Sử  dụng  các  chương  trình  all-­‐in-­‐one:  “Packer”  •  ASPack  •  ASProtect  •  PECompact  •  PECrypt  •  Themida  •   –  Code-­‐sign  ứng  dụng  bằng  chữ  ký  số  ­‐us/library/ms537361%28v=vs.85%29.aspx  •  Trên  các  hệ  điều  hành  khác  –  Đang  tiến  dần  đến  xu  hướng  code-­‐sign:  VD  iOS,  MacOS   7.7  Giải  pháp  tổng  thể   130   1.      Tìm  hiểu  và  minh  hoạ  các  kỹ  thuật  SQL  Injection  hiện  nay  (đặc  biệt  là  blind  sql  injection).(Tuần  14  -­‐  Thuý)  2.    Tìm  hiểu  và  minh  hoạ  kỹ  thuật  tấn  công  tràn  bộ  đệm  buffer  over}low  và  khai  thác  qua  shellcode.  Có  thể  dùng  Metasploit  để  thử  nghiệm.(Tuần  15-­‐  Xuan  Hiep)  3.      Tìm  hiểu  cơ  chế  leo  thang  đặc  quyền  trên  một  thiết  bị  chạy  hệ  điều  hành  Android  (rooting,  tìm  cái  dễ  root  nhất).(Tuần  15  –  Phi  Hiệp)  4.    Sử  dụng  một  trong  các  kỹ  thuật  đồng  bộ  để  thực  hiện  thuật  toán  quicksort  trên  bộ  vi  xử  lý  đa  nhân.  Yêu  cầu  tốc  độ  sắp  xếp  phải  đạt  được  tuyến  tính  với  số  nhân  của  bộ  vi  xử  lý.(Tuần  12  –  Ngọc  Anh)  5.    Sử  dụng  thuật  toán  HMAC  để  phát  hiện  thay  đổi  trong  mã  lệnh  của  chương  trình.  Với  key  và  giá  trị  băm  được  tải  về  từ  internet  trong  mỗi  lần  kiểm  tra.(Tuần  12  -­‐  Linh)  6.    Sử  dụng  chữ  ký  số  để  phát  hiện  thay  đổi  trong  mã  lệnh  của  chương  trình.  Với  public  key  được  tải  về  từ  internet  trong  mỗi  lần  kiểm  tra.(Tuần  13  –  Quynh,  Thành)  7.    Tìm  hiểu  các  kỹ  thuật  phát  hiện  debugger  (anti-­‐debugger)  và  các  kỹ  thuật  chống  phát  hiện  debugger  (anti-­‐anti-­‐debugger).(Tuần  13  –  Hoa,  Tùng)  8.    Xây  dựng  hệ  thống  cấp  phát  chứng  thực  số  dựa  trên  openssl  với  CA  sinh  sẵn  Chỉ  yêu  cầu  viết  bằng  php/html  để  nhận  tham  số  của  chứng  thực  qua  form,  sau  đó  sinh  ngay  cặp  chứng  thực/key  cho  client  và  biểu  diễn  dưới  dạng  PEM  (.crt,  .key)  (Tuần  14  –  Dat)   Các  đề  tài  tìm  hiểu   131  

Các file đính kèm theo tài liệu này:

  • pdfbai_giang_lap_trinh_an_toan_luong_anh_hoang.pdf