base64 编码

#include <cstdlib>
#include <cstring>
#include <iostream>
 
using namespace std;
 
static const char base64_charset[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
int base64_encode(uint8_t in[], uint8_t out[]) { // unsafe
    size_t in_len = strlen(reinterpret_cast<char *>(in));
    if (in_len == 0)
        return 0;
    size_t i = 0, j = 0;
    while (i < in_len) {
        uint8_t c1 = i < in_len ? in[i++] : 0;
        uint8_t c2 = i < in_len ? in[i++] : 0;
        uint8_t c3 = i < in_len ? in[i++] : 0;
        out[j++] = base64_charset[c1 >> 2];
        out[j++] = base64_charset[(c1 & 3) << 4 | (c2 >> 4)];
        out[j++] =
            i < in_len + 2 ? base64_charset[(c2 & 15) << 2 | (c3 >> 6)] : '=';
        out[j++] = i < in_len + 1 ? base64_charset[c3 & 63] : '=';
    }
    return j;
}
 
int main() {
    char test[] = "this is an example";
    char res[100] = {};
    size_t reslen = base64_encode((uint8_t *)test, (uint8_t *)res);
    cout << res << endl << reslen << endl;
}

RC4

#include <cstdlib>
#include <cstring>
#include <iostream>
 
using namespace std;
 
inline void swap_elements(uint8_t *S, uint8_t a, uint8_t b) {
    uint8_t tmp = S[a];
    S[a] = S[b];
    S[b] = tmp;
}
 
void rc4_skip(const uint8_t *key, size_t key_len, size_t skip, uint8_t *data,
              size_t data_len) {
    uint8_t S[256], *pos = data;
    size_t kpos = 0;
 
    // Setup RC4 state
    for (uint32_t i = 0; i < 256; i++) {
        S[i] = i;
    }
    for (uint32_t i = 0, j = 0; i < 256; i++) {
        j = (j + S[i] + key[kpos++]) & 0xff;
        if (kpos >= key_len) {
            kpos = 0;
        }
        swap_elements(S, i, j);
    }
 
    // Skip the start of the stream
    uint32_t i = 0, j = 0;
    for (uint32_t k = 0; k < skip; k++) {
        i = (i + 1) & 0xff;
        j = (j + S[i]) & 0xff;
        swap_elements(S, i, j);
    }
 
    // Apply RC4 to data
    for (uint32_t k = 0; k < data_len; k++) {
        i = (i + 1) & 0xff;
        j = (j + S[i]) & 0xff;
        swap_elements(S, i, j);
        *pos++ ^= S[(S[i] + S[j]) & 0xff];
    }
}
 
void rc4(uint8_t *buf, size_t len, const uint8_t *key, size_t key_len) {
    rc4_skip(key, key_len, 0, buf, len);
}
 
int main() {
    char test[100] = "this is an example";
    char key[100] = "key";
    size_t test_len = strlen(test);
    rc4((uint8_t *)test, test_len, (uint8_t *)key, strlen(key));
    cout << test << endl;
    // decrypt
    rc4((uint8_t *)test, test_len, (uint8_t *)key, strlen(key));
    cout << test << endl;
}

IDA 里反编译效果(clang++ -Ofast)

do
  {
    v21 = *((_BYTE *)&v50[0].__locale_ + v18);
    v19 += v21 + v34[v20];
    if ( v20 + 1 < v5 )
      ++v20;
    else
      v20 = 0LL; //S盒初始化交换
    *((_BYTE *)&v50[0].__locale_ + v18) = *((_BYTE *)&v50[0].__locale_ + v19);
    *((_BYTE *)&v50[0].__locale_ + v19) = v21;
    ++v18;
  }
  while ( v18 != 256 );
  if ( v3 )
  {
    v22 = 0LL;
    v23 = 0;
    LOBYTE(v24) = 0;
    do
    {
      v24 = (unsigned __int8)(v24 + 1);
      v25 = *((unsigned __int8 *)&v50[0].__locale_ + v24);
      v23 += v25;
      *((_BYTE *)&v50[0].__locale_ + v24) = *((_BYTE *)&v50[0].__locale_ + (unsigned __int8)v23); // S盒加密交换
      *((_BYTE *)&v50[0].__locale_ + (unsigned __int8)v23) = v25;
      __s[v22++] ^= *((_BYTE *)&v50[0].__locale_ + (unsigned __int8)(*((_BYTE *)&v50[0].__locale_ + v24) + v25)); // 最后的RPG流异或
    }
    while ( v3 > (unsigned int)v22 );
  }

特征点在前面的交换与最后只有一次的异或流操作