首页 > 其他分享 >Proxifier Portable Edition v4.12 注册分析

Proxifier Portable Edition v4.12 注册分析

时间:2024-10-20 15:32:11浏览次数:1  
标签:Myres Portable Proxifier v4.12 v29 wstring WS key ._

Proxifier Portable Edition v4.12

目录

MFC 程序分析

可从以下方面入手

1、res

查找是否存在静态dialog资源,(没有就上xspy)

image-20241020151224186

2、DoDataExchange

数据绑定

3、GetMessageMap

消息映射;此文不涉及

struct AFX_MSGMAP_ENTRY
{
        UINT nMessage;   // windows message
        UINT nCode;      // control code or WM_NOTIFY code
        UINT nID;        // control ID (or 0 for windows messages)
        UINT nLastID;    // used for entries specifying a range of control id's
        UINT_PTR nSig;       // signature type (action) or pointer to message #
        AFX_PMSG pfn;    // routine to call (or special value)
};

struct AFX_MSGMAP
{
	const AFX_MSGMAP *(__stdcall *pfnGetBaseMap)();
	const AFX_MSGMAP_ENTRY *lpEntries;
};

CRegistrationDlg

CDialog 主要关注DoDataExchange 和OnOK

image-20241020151824234

CRegistrationDlg__DoDataExchange_487450

结合ResourceHacker 可得到CRegistrationDlg 相关数据信息

void __thiscall CRegistrationDlg::DoDataExchange_487450(CRegistrationDlg *this, struct CDataExchange *a2)
{
  // {
  //    CONTROL "", 1017, EDIT, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 23, 38, 208, 14 
  //    CONTROL "", 1018, EDIT, ES_LEFT | ES_UPPERCASE | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 23, 77, 208, 14 
  //    CONTROL "Current user only", 1006, BUTTON, BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP, 23, 129, 98, 10 
  //    CONTROL "All users on this computer\n(require administrator)", 1007, BUTTON, BS_AUTORADIOBUTTON | BS_MULTILINE | WS_CHILD | WS_VISIBLE, 129, 123, 102, 22 
  //    CONTROL "OK", 1, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 166, 50, 14 
  //    CONTROL "Cancel", 2, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 199, 166, 50, 14 
  //    CONTROL "Please enter your registration information", -1, BUTTON, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 7, 7, 242, 98 
  //    CONTROL "Your name or company name:", -1, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 23, 25, 101, 8 
  //    CONTROL "Your registration key:", -1, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 23, 63, 101, 8 
  //    CONTROL "Set this license for", -1, BUTTON, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 7, 114, 242, 38 
  // }
  DDX_Control(a2, 1017, &this->name_CEdit_B8);
  DDX_Text(a2, 1017, &this->name_text138);
  DDX_Control(a2, 1018, &this->key_CEdit_140);
  DDX_Text(a2, 1018, &this->key_text_1C0);
  DDX_Radio(a2, 1006, &this->Current_user_only_1C4);
  DDX_Control(a2, 1006, &this->Current_user_only_CButton_1C8);
}

CRegistrationDlg__OnOK_4874E0

注册逻辑在Register_471DC0中

void __thiscall CRegistrationDlg::OnOK_4874E0(CRegistrationDlg *this)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  CWnd::UpdateData(this, 1);
  if ( *(this->name_text138 - 3) )
  {
    v3 = (this->key_text_1C0 - 0x10);
    if ( *(v3 + 1) )
    {
      if ( this->Current_user_only_1C4 )
      {
        CWnd::MessageBoxW(
          this,
          L"Portable Edition cannot be registered for all users of this computer.\n"
           "Please register the current instance only.",
          L"Registration",
          0x30u);
      }
      else
      {
        flag = 1;
        key = v2;
        p_key = &key;
        v10 = &key;
        key = (get_text_40ADB0(v3) + 4);
        v12 = 0;
        v4 = (this->name_text138 - 0x10);
        v10 = &v7;
        name = get_text_40ADB0(v4);
        v12 = 0xFFFFFFFF;
        if ( Register_471DC0(v6, name + 8, key, flag) )
          CDialog::OnOK(this);
      }
    }
    else
    {
      CWnd::MessageBoxW(this, L"Key cannot be empty.", L"Registration", 0x30u);
    }
  }
  else
  {
    CWnd::MessageBoxW(this, L"Name cannot be empty.", L"Registration", 0x30u);
  }
}

Register_471DC0

image-20241020152333237

do_check_43C500

key[2] == 'Y' 时 The registration key from Proxifier v2 doesn't work with Proxifier v4.

char __thiscall do_check_43C500(LicInfo *this, wchar_t *name, wchar_t *key, std_wstring *k, int a5, std_wstring *Src)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  v30 = name;
  v25._Mysize = 0;
  v25._Myres = 7;
  v25.u._Buf[0] = 0;
  v7 = key;
  LODWORD(src) = key;
  HIDWORD(src) = key + 1;
  while ( *v7++ )
    ;
  wstring_402B60(&v25, src, (v7 - HIDWORD(src)) >> 1);
  if ( !sub_402280(k, v25.u._Ptr) )
  {
    wstring_402B60(
      Src,
      L"The format of the registration key is incorrect.\n"
       "\n"
       "A correct key should look like the following:\n"
       "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX\n"
       "\n"
       "If the problem persists, please contact support.",
      0xAFu);
    return 0;
  }
  Ptr = k;
  if ( k->_Myres >= 8u )
    Ptr = k->u._Ptr;
  if ( Ptr[2] == 'Y' )
  {
    wstring_402B60(
      Src,
      L"The registration key is incorrect.\n"
       "\n"
       "The registration key from Proxifier v2 doesn't work with Proxifier v4. Please upgrade your license.\n"
       "If you have any questions please contact support.",
      0xB9u);
    return 0;
  }
  v26 = Src;
  memset(&v29, 0, 0xC);
  v29.year_10 = 0;
  v29.mon_14 = 0;
  v29.calc_part3_1c = 0;
  sub_43D770(&v25, k);
  if ( !check_key_402430(&v29, v25, v26) )
  {
    wstring_402B60(
      Src,
      L"The registration key is incorrect.\n"
       "\n"
       "Please check that you have entered it correctly.\n"
       "If the problem persists, please contact support.",
      0x85u);
    return 0;
  }
  if ( v29.Edition_id_0 == this->Edition_id )
  {
    if ( v29.product_version_4 != this->product_version )
    {
      wstring_402B60(
        Src,
        L"This registration key is for another version of this product.\n"
         "It cannot be used with this version.\n"
         "\n"
         "If you have any questions please contact support.",
        0x95u);
      return 0;
    }
    if ( v29.product_version_low_8 < this->product_version_low )
    {
      wstring_402B60(
        Src,
        L"This registration key is for an older version of this product.\n"
         "It cannot be used with the current version. Please update your license.\n"
         "\n"
         "If you have any questions please contact support.",
        0xB9u);
      return 0;
    }
    if ( v29.year_10 )
    {
      v35.tm_year = v29.year_10 - 0x76C;
      v35.tm_mon = v29.mon_14;
      memset(&v35, 0, 0xC);
      memset(&v35.tm_wday, 0, 0xC);
      v35.tm_mday = 1;
      LODWORD(v18) = sub_60E285(&v35);
      src = v18;
      v19 = _time64(0);
      v31 = src - v19;
      if ( ((src - v19) >> 0x20) > 0 )
      {
        v20 = v31;
      }
      else if ( (((src - v19) >> 0x20) & 0x80000000) != 0i64 || (v20 = v31) == 0 )
      {
        sub_60B38F(v36, 0x1FF, L"This registration key expired on %B %d, %Y \n", &v35);
        wstring_402B60(Src, v36, wcslen(v36));
        sub_420700(Src, L"Please update your license.\n\nIf you have any questions please contact support.", 0x4Eu);
        return 0;
      }
      this->expired_time_10 = src;
      this->Days_until_expiration_4 = v20 / 0x15180;
    }
    else
    {
      this->expired_time_10 = 0i64;
    }
    v21 = v30;
    v22 = v30;
    this->registration_1 = 1;
    this->is_not_expired_8 = 1;
    v23 = v22 + 1;
    while ( *v22++ )
      ;
    wstring_402B60(&this->name_1C, v21, v22 - v23);
    sub_402CC0(&this->dword34, k);
    this->dword18 = v29.dw_c;
    return 1;
  }
  else
  {
    v33._Mysize = 0;
    v33._Myres = 7;
    v33.u._Buf[0] = 0;
    v37 = 0;
    if ( v29.Edition_id_0 >= 3 )
    {
      v26 = 0xF;
      v25._Myres = L"another product";
    }
    else
    {
      v11 = Edition_str_6A0C30[v29.Edition_id_0];
      v26 = wcslen(v11);
      v25._Myres = v11;
    }
    wstring_402B60(&v33, v25._Myres, v26);
    v34._Mysize = 0;
    v34._Myres = 7;
    v34.u._Buf[0] = 0;
    LOBYTE(v37) = 1;
    Edition_id = this->Edition_id;
    if ( Edition_id >= 3 )
    {
      v26 = 0xC;
      v25._Myres = L"this product";
    }
    else
    {
      v13 = Edition_str_6A0C30[Edition_id];
      v26 = wcslen(v13);
      v25._Myres = v13;
    }
    wstring_402B60(&v34, v25._Myres, v26);
    v14 = sub_431500(&v29.product_version_low_8, L"This registration key is for ", &v33);
    LOBYTE(v37) = 2;
    v15 = sub_43D270(&v35.tm_mday, v14, L".\nIt cannot be used with ");
    LOBYTE(v37) = 3;
    v16 = sub_431D20(&v27, v15, &v34);
    LOBYTE(v37) = 4;
    v17 = sub_43D270(v28, v16, L".\n\nIf you have any questions please contact support.");
    sub_420820(v17);
    sub_402EE0(v28);
    sub_402EE0(&v27);
    sub_402EE0(&v35.tm_mday);
    sub_402EE0(&v29.product_version_low_8);
    sub_402EE0(&v34);
    sub_402EE0(&v33);
    return 0;
  }
}

check_key_402430 #校验key的关键点

char __thiscall check_key_402430(CheckRet *this, std_wstring key, std_wstring *out_result)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  v31 = out_result;
  check_data[6] = 0;
  // XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
  // 0-4 5 6-10 11 12-16 17 18-22 23 24-28
  if ( key._Mysize == 29 )
  {
    p_key = &key;
    if ( key._Myres >= 8u )
      p_key = key.u._Ptr;
    // 去除‘-’
    wstring_remove_4027E0(&key, &t_calc_part4, p_key + 46);// [13]
    Ptr = &key;
    if ( key._Myres >= 8u )
      Ptr = key.u._Ptr;
    wstring_remove_4027E0(&key, &t_calc_part4, Ptr + 34);// [17]
    v7 = &key;
    if ( key._Myres >= 8u )
      v7 = key.u._Ptr;
    wstring_remove_4027E0(&key, &t_calc_part4, v7 + 22);// [11]
    v8 = &key;
    if ( key._Myres >= 8u )
      v8 = key.u._Ptr;
    wstring_remove_4027E0(&key, &t_calc_part4, v8 + 0xA);// [5]
    // 移除‘-’后25d 个字符
    v9 = &key;
    if ( key._Myres >= 8u )
      v9 = key.u._Ptr;
    v10 = v9[14];                               // [14]
    v11 = &key;
    if ( key._Myres >= 8u )
      v11 = key.u._Ptr;
    t_calc_part4 = &v29;
    // plain_key[2]=>plain_key[14]
    v11[2] = v10;
    v29._Mysize = 0;
    v29._Myres = 7;
    v29.u._Buf[0] = 0;
    if ( key._Mysize < 20 )
      sub_402AF0();
    v12 = 5;
    v13 = 5;
    if ( key._Mysize - 20 < 5 )
      v13 = key._Mysize - 20;
    v14 = &key;
    if ( key._Myres >= 8u )
      v14 = key.u._Ptr;
    // 最后一部分
    // part4  ==>[20:]
    wstring_402B60(&v29, v14 + 0x14, v13);
    t_calc_part4 = custom_checksum_402740(v29);
    calc_part4 = t_calc_part4 ^ (t_calc_part4 << 7);
    temp = &v29;
    v29._Mysize = 0;
    v29._Myres = 7;
    v29.u._Buf[0] = 0;
    if ( key._Mysize < 0xF )
      sub_402AF0();
    if ( key._Mysize - 0xF < 5 )
      v12 = key._Mysize - 0xF;
    v16 = &key;
    if ( key._Myres >= 8u )
      v16 = key.u._Ptr;
    // 倒数第二部分
    // part3  ==>[15:+5(max)]
    wstring_402B60(&v29, v16 + 0xF, v12);
    this->calc_part3_1c = custom_checksum_402740(v29);
    v17 = 7;
    temp = &v29;
    Mysize = 7;
    v29._Mysize = 0;
    v29._Myres = 7;
    v29.u._Buf[0] = 0;
    v19 = &key;
    if ( key._Mysize < 7 )
      Mysize = key._Mysize;
    if ( key._Myres >= 8u )
      v19 = key.u._Ptr;
    // [:7]
    wstring_402B60(&v29, v19->u._Buf, Mysize);
    temp = custom_checksum_402740(v29);
    v30 = &v29;
    v29._Mysize = 0;
    v29._Myres = 7;
    v29.u._Buf[0] = 0;
    if ( key._Mysize < 7 )
      sub_402AF0();
    if ( key._Mysize - 7 < 7 )
      v17 = key._Mysize - 7;
    v20 = &key;
    if ( key._Myres >= 8u )
      v20 = key.u._Ptr;
    // [7:+7(max)]
    wstring_402B60(&v29, &v20->u._Buf[7], v17);
    data1 = calc_part4 ^ custom_checksum_402740(v29) ^ 0x87654321;
    data0 = calc_part4 ^ temp ^ 0x12345678;
    check_data[0] = data0;
    check_data[2] = this->calc_part3_1c;
    xxcrc32_value = 0xFFFFFFFF;
    check_data[1] = data1;
    // xx_crc32
    for ( i = 0; i < 0xC; ++i )
    {
      xxcrc32_value ^= *(check_data + i) << 0x18;
      v24 = 8;
      do
      {
        if ( xxcrc32_value >= 0 )
          xxcrc32_value *= 2;
        else
          xxcrc32_value = (2 * xxcrc32_value) ^ 0x4C11DB7;
        --v24;
      }
      while ( v24 );
    }
    if ( t_calc_part4 == (xxcrc32_value & 0x1FFFFFF) )
    {
      v25 = data0;
      v26 = HIWORD(data0) & 0x1F;
      // 0 'Proxifier Standard Edition'
      // 1 'Proxifier Portable Edition'
      // 2 'Proxifier for Mac'
      this->Edition_id_0 = data0 >> 0x15;       // 1
      this->product_version_4 = v26;            // 0
      this->product_version_low_8 = v25 >> 5;   // 0x190
      v27 = HIWORD(data1);                      // 高WORD字节设置为0,则不设置过期时间
      this->dw_c = v25 & 0x1F;
      this->dw_18 = data1;
      if ( HIWORD(data1) ) // 0 时不过期
      {
        this->year_10 = v27 / 12 + 2000;       
        v27 %= 12u;
      }
      else
      {
        this->year_10 = v27;                    // 0 时不过期
      }
      this->mon_14 = v27;
      v4 = 1;
    }
    else
    {
      wstring_402B60(v31, L"Incorrect key", 0xDu);
      v4 = 0;
    }
  }
  else
  {
    wstring_402B60(out_result, L"Incorrect key length.", 0x15u);
    v4 = 0;
  }
  sub_402EE0(&key);
  return v4;
}

custom_checksum_402740

int __stdcall custom_checksum_402740(std_wstring a1)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  checksum = 0;
  for ( i = a1._Mysize - 1; i >= 0; --i )
  {
    current_checksum = 0x20 * checksum;
    Ptr = &a1;
    if ( a1._Myres >= 8 )
      Ptr = a1.u._Ptr;
    temp_char = Ptr->u._Buf[i];
    if ( temp_char == 'W' )
    {
      LOWORD(temp_char) = '0';
      add = current_checksum - 0x30;
    }
    else
    {
      switch ( temp_char )
      {
        case 'X':
          LOWORD(temp_char) = 'O';
          break;
        case 'Y':
          LOWORD(temp_char) = '1';
          add = current_checksum - 0x30;
          goto LABEL_9;
        case 'Z':
          LOWORD(temp_char) = 'I';
          break;
        default:
          if ( (temp_char - 0x30) <= 9u )
          {
            add = current_checksum - 0x30;
            goto LABEL_9;
          }
          break;
      }
      add = current_checksum - 0x37;
    }
LABEL_9:
    checksum = temp_char + add;
  }
  sub_402EE0(&a1);
  return checksum;
}

py


from enum import Enum
import random
from typing import Sequence
import string

str_table=string.ascii_uppercase+string.digits

class Product(Enum):
    Standard=0
    Portable=1
    Mac=2


def xx_crc32(data:bytes):
    crc_value = 0xFFFFFFFF
    for i in range(len(data)):
        crc_value ^= data[i] << 0x18
        for j in range(8):
            crc_value= 2*crc_value if crc_value<0x80000000 else (2 * crc_value) ^ 0x4C11DB7
            crc_value &= 0xffffffff
    return crc_value


def custom_checksum(input_str:Sequence):
    
    if isinstance(input_str,bytes):
        input_str=input_str.decode()
    elif isinstance(input_str,(tuple,list)):
        input_str=''.join(input_str)
    input_len = len(input_str)  # 字符串长度
    checksum = 0  
    for i in range(input_len - 1, -1, -1):
        current_sum = 0x20 * checksum  

        char = input_str[i] 
        temp_char = ord(char)  

        if char == 'W':
            temp_char = ord('0')  # 'W' 替换为 '0'
            add_value = current_sum - 0x30
        elif char == 'X':
            temp_char = ord('O')  # 'X' 替换为 'O'
            add_value = current_sum - 0x37
        elif char == 'Y':
            temp_char = ord('1')  # 'Y' 替换为 '1'
            add_value = current_sum - 0x30
        elif char == 'Z':
            temp_char = ord('I')  # 'Z' 替换为 'I'
            add_value = current_sum - 0x37
        elif '0' <= char <= '9':  # 如果字符是数字
            add_value = current_sum - 0x30
        else:
            add_value = current_sum - 0x37

        checksum = temp_char + add_value  

    return checksum&0xffffffff
def re_custom_checksum(checksum:int,output_len:int):
    checksum&=0xffffffff
    output_str=['' for i in range(output_len)]
    for i in range(output_len):
        
        temp_value=checksum%0x20
        checksum//=0x20

        if temp_value==ord('0')-0x30:
            output_str[i]='W'
        elif temp_value==ord('O')-0x37:
            output_str[i]='X'
        elif temp_value==ord('1')-0x30:
            output_str[i]='Y'
        elif temp_value==ord('I')-0x37:
            output_str[i]='Z'
        elif 0<=temp_value<=9:
            output_str[i]=str(temp_value)
        else:
            output_str[i]=chr(temp_value+0x37)

    return ''.join(output_str)



def check_key(key:str):
    if '-' in key:
        key=key.replace('-','')
    assert len(key)==25,"key len need 25!"
    key_list=list(key)
    key_list[2]=key_list[14]
    t_calc_part4=custom_checksum(key_list[20:])            
    calc_part4=(t_calc_part4^(t_calc_part4<<7))&0xffffffff 
    calc_part3=custom_checksum(key_list[15:20])            
    calc_part0_1=custom_checksum(key_list[:7])             
    calc_part1_2=custom_checksum(key_list[7:14])


    
    check_data0=calc_part0_1^calc_part4^0x12345678
    # print('[-]check_data0:',check_data0)
    check_data1=calc_part4^calc_part1_2^0x87654321
    # print('[-]check_data1:',check_data1)
    check_data2=calc_part3
    # print('[-]check_data2:',check_data2)
    check_data=check_data0.to_bytes(4,'little')+check_data1.to_bytes(4,'little')+check_data2.to_bytes(4,'little')
    # print('[-]check_data:',check_data.hex())
    xxcrc32_value=xx_crc32(check_data)
    # print('[-]xxcrc32_value:',xxcrc32_value&0x1FFFFFF)
    return (t_calc_part4==xxcrc32_value&0x1FFFFFF)



'''
  // .rdata:006BB080 dword_6BB080    dd 1    ;Edition_id                ; DATA XREF: sub_46DF40+69↑r
  // .rdata:006BB084                 dd 0    ;product_version
  // .rdata:006BB088                 dd 190h ;product_version_low
  // .rdata:006BB08C                 dd 1Fh
'''
def gen_key(product:Product=Product.Portable,version_low:int=0x190):


    key_14=random.choice(string.ascii_uppercase.replace('Y',''))

    '''
    check_data0

    HIWORD >> 0x15为产品id
        // 0 'Proxifier Standard Edition'
        // 1 'Proxifier Portable Edition'
        // 2 'Proxifier for Mac'

    HIWORD &0x1f 为0    

    >>5  需大于版本0x190

    '''
    check_data0=(product.value<<0x15) | random.randint(version_low<<5,0xffff) 
    # print('[-]data0:',check_data0)


    '''
    check_data1

    HIWORD(data1);                      // 高WORD字节设置为0,则不设置过期时间
    '''
    check_data1=random.randint(0,0xffff)
    # print('[-]data1:',check_data1)

    '''
    check_data2  随机

    check_data2=calc_part3
    '''
    
    part3_str=''.join(random.choices(str_table,k=5))
    calc_part3=custom_checksum(part3_str)
    '''
    [15-20]
    '''
    part3_str=re_custom_checksum(calc_part3,5)

    check_data2=calc_part3
    # print('[-]data2:',check_data2)
    check_data=check_data0.to_bytes(4,'little')+\
            check_data1.to_bytes(4,'little')+\
            check_data2.to_bytes(4,'little')
    
    # print('[-]re_check_data:',check_data.hex())
    t_calc_part4=xx_crc32(check_data)&0x1FFFFFF
    # print('[-]t_calc_part4:',t_calc_part4)
    '''
    [20-25]
    '''
    part4_str=re_custom_checksum(t_calc_part4,5)
    
    calc_part4=(t_calc_part4^(t_calc_part4<<7))&0xffffffff #可得


    calc_part0_1=check_data0^calc_part4^0x12345678
    '''
    [0-7]
    '''
    part0_1_str=re_custom_checksum(calc_part0_1,7)  
    
    calc_part1_2=check_data1^calc_part4^0x87654321
    '''
    [7-14]
    '''
    part1_2_str=re_custom_checksum(calc_part1_2,7)
    
    '''
    正向计算时 [2]=[14],故逆向后part0_1_str 的[2]移动到[14]位置
    '''
    key=part0_1_str[:2]+key_14+part0_1_str[3:]+part1_2_str+part0_1_str[2]+part3_str+part4_str
    list_key=list(key)
    # print(key)
    k='-'.join([''.join(list_key[i:i+5]) for i in range(0,25,5) ])
    return k


def test():
    k=gen_key(Product.Portable)
    print(k)

    x=check_key(k)
    print('check:',x)

if __name__=='__main__':
    # test()
    k=gen_key(Product.Portable,0x190)
    print(k)

ps

image-20241020145235261

image-20241020145339771

标签:Myres,Portable,Proxifier,v4.12,v29,wstring,WS,key,._
From: https://www.cnblogs.com/DirWang/p/18487371

相关文章

  • 几何透视图像校正处理软件 DxO ViewPoint v4.12 中文授权版
    DxOViewPoint是DxOLabs旗下一款行业领先级几何透视图像校正处理软件。DxOViewPoint让您可以完全掌控线条、角度和形状。调整透视、修复畸变、改变特定区域形状和校正广角拉伸,以获取精美图像。DxOViewPoint可作为独立应用程序运行,也可作为DxOPhotoLab中的工具面板以及......
  • Proxifier 是一个网络工具,用于通过代理服务器重定向应用程序的网络流量。它使你能够将
    Proxifier是一个网络工具,用于通过代理服务器重定向应用程序的网络流量。它使你能够将所有网络流量或特定应用程序的流量通过代理服务器发送,从而增强隐私、绕过地理限制或访问受限内容。为什么使用Proxifier?隐私保护:通过代理服务器隐藏真实IP地址,增强在线隐私。绕过限制:访......
  • FL Studio Portable 21.2.3.4004破解版
    ​FLStudioPortable21.2.3.4004破解版是很多音乐人都在用的全功能的音乐工作站,里面拥有非常先进的制作工具,音符编辑器,音效编辑器,便捷的音源输入,让用户可以自由的在这里自由的改编歌曲,打造出你想要的曲风效果,操作方便,推荐给玩音乐的朋友!FLStudio21.2.3.4004破解版是一款D......
  • ARC179D Portable Gate
    题意简述有一棵树\(n\)个点,你有一个门,你现在从一个你选定的点开始走,目标是所有点都至少访问一次。每次你可以选择:经过一条树边走到相邻点,花费\(1\)。将门放在当前点。将自己传送到门所在的点。求最小花费。\(n\le2\times10^5\)。分析先考虑根(出发点)固定怎么做。由于......
  • proxifier+v2代理软件实现真全局代理(防溯源)
    v2的使用这里就不详细说了打开v2,右下角可以看到端口开启v2代理后,打开proxifer先打开左上角的代理服务器按照以下配置,端口改成v2上面看到的socks5端口也可以左下角检查以下代理有没有问题,有时候可能是代理服务器卡了或者死了接着来到代理规则,按照以下配置......
  • 使用Proxifier玩转代理
    使用Proxifier玩转代理Proxifier介绍​Proxifier​是一款代理客户端软件,可以让不支持代理服务器工作的程序变的可行。支持各种操作系统和各代理协议,它的运行模式可以指定端口,指定程序的特点。​Proxifier​的主要用途是在系统级别通过代理服务器强制Web请求,从而使来自不支......
  • PNG格式PNG(Portable Network Graphics)位图图形文件格式 无损压缩的图片格式,支持索引
    PNG(PortableNetworkGraphics)是一种位图图形文件格式,它是一种无损压缩的图片格式,支持索引、灰度、RGB和RGBA等多种颜色模式。PNG格式支持多种颜色模式,包括以下几种:索引色模式(IndexedColor):索引色模式使用一个颜色索引表来存储图像中使用的颜色。每个像素使用索引值来指定......
  • 将软件随身携带——portableapps使用
    引言你是否曾有过这样的欲望,把软件装到u盘里,到哪里都可以随时使用,如果是这样的话,那么这篇文章你一定要看!什么是便携式应用便携式应用可不是光不用安装,把软件安装文件夹拷贝到u盘就完事了,便携式应用可以把软件+数据一同带在u盘里,这样走到哪里,都可以“即插即用”。PortableApps......
  • VS Code 便携模式(Portable Mode)的制作
    VisualStudioCode支持便携式模式。此模式使VSCode创建和维护的所有数据都位于其自身附近,因此可以跨环境移动。此模式还提供了一种设置VSCode扩展的安装文件夹位置的方法,对于阻止在企业环境将扩展安装在WindowsAppData文件夹中非常有用。Windows的ZIP下载、Linux......
  • Proxifier+Burp 抓取微信PC端小程序数据包
    由于工作要求,需要抓取微信小程序的数据包,如是了解了一下,简直是解放了一片新大陆啊!以下是记录Proxifier+Burp使用过程。现有环境BurpSuite可正常使用,能抓取浏览器HTTP/HTTPS流量。(BurpSuite的安装以及使用方法可自行百度)BurpSuite代理设置为如下图:Proxifier+Burp抓取微信H......