• PE查看器


    主要界面如下:

    主要代码如下:

      1 BOOL CPEParseDlg::OnInitDialog()
      2 {
      3     CDialog::OnInitDialog();
      4 
      5     // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
      6     //  执行此操作
      7     SetIcon(m_hIcon, TRUE);            // 设置大图标
      8     SetIcon(m_hIcon, FALSE);        // 设置小图标
      9 
     10     // TODO: 在此添加额外的初始化代码
     11     InitSectionList();
     12 
     13     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
     14 }
     15 
     16 // 如果向对话框添加最小化按钮,则需要下面的代码
     17 //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
     18 //  这将由框架自动完成。
     19 
     20 void CPEParseDlg::OnPaint()
     21 {
     22     if (IsIconic())
     23     {
     24         CPaintDC dc(this); // 用于绘制的设备上下文
     25 
     26         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
     27 
     28         // 使图标在工作区矩形中居中
     29         int cxIcon = GetSystemMetrics(SM_CXICON);
     30         int cyIcon = GetSystemMetrics(SM_CYICON);
     31         CRect rect;
     32         GetClientRect(&rect);
     33         int x = (rect.Width() - cxIcon + 1) / 2;
     34         int y = (rect.Height() - cyIcon + 1) / 2;
     35 
     36         // 绘制图标
     37         dc.DrawIcon(x, y, m_hIcon);
     38     }
     39     else
     40     {
     41         CDialog::OnPaint();
     42     }
     43 }
     44 
     45 //当用户拖动最小化窗口时系统调用此函数取得光标
     46 //显示。
     47 HCURSOR CPEParseDlg::OnQueryDragIcon()
     48 {
     49     return static_cast<HCURSOR>(m_hIcon);
     50 }
     51 
     52 
     53 void CPEParseDlg::OnBnClickedButtonLook()
     54 {
     55     // TODO: 在此添加控件通知处理程序代码
     56     ((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->GetWindowText(m_strPathName);
     57     m_strPathName = m_strPathName.Trim();
     58     if (m_strPathName.IsEmpty())
     59     {
     60         AfxMessageBox(_T("请选择要查看的文件!"));
     61         return;
     62     }
     63 
     64     FileCreate();
     65     if (FALSE == IsPeFileAndGetPePointer())
     66     {
     67         AfxMessageBox(_T("该文件不是PE文件!"));
     68         return;
     69     }
     70     ParseBasePe();
     71     EnumSections();
     72 }
     73 
     74 void CPEParseDlg::OnBnClickedButtonExit()
     75 {
     76     // TODO: 在此添加控件通知处理程序代码
     77     OnOK();
     78 }
     79 
     80 void CPEParseDlg::OnBnClickedButtonBrowse()
     81 {
     82     // TODO: 在此添加控件通知处理程序代码
     83     CFileDialog FileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, _T("Executeable Files (*.exe)|*.exe|Dynamic Linker Library Files (*.dll)|*.dll|OCX Files (*.ocx)|*.ocx|Driver Files (*.sys)|*.sys||"));
     84     FileDlg.DoModal();
     85     CString strPathName = FileDlg.GetPathName();
     86     ((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->SetWindowText(strPathName);
     87 }
     88 
     89 BOOL CPEParseDlg::FileCreate(void)
     90 {
     91     BOOL bRet = FALSE;
     92 
     93     m_hFile = CreateFile(m_strPathName.GetBuffer(0), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     94     if (INVALID_HANDLE_VALUE == m_hFile)
     95     {
     96         return bRet;
     97     }
     98 
     99     m_hMap = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
    100     if (NULL == m_hMap)
    101     {
    102         CloseHandle(m_hFile);
    103         return bRet;
    104     }
    105 
    106     m_lpBase = MapViewOfFile(m_hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    107     if (NULL == m_lpBase)
    108     {
    109         CloseHandle(m_hMap);
    110         CloseHandle(m_hFile);
    111         return bRet;
    112     }
    113 
    114     bRet = TRUE;
    115     return bRet;
    116 }
    117 
    118 void CPEParseDlg::InitSectionList(void)
    119 {
    120     CRect Rect;
    121     m_ctrlSections.GetClientRect(&Rect);
    122     m_ctrlSections.SetExtendedStyle(m_ctrlSections.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    123     m_ctrlSections.InsertColumn(0, _T("节名"));
    124     m_ctrlSections.InsertColumn(1, _T("V.偏移"));
    125     m_ctrlSections.InsertColumn(2, _T("V.大小"));
    126     m_ctrlSections.InsertColumn(3, _T("R.偏移"));
    127     m_ctrlSections.InsertColumn(4, _T("R.大小"));
    128     m_ctrlSections.InsertColumn(5, _T("标志"));
    129     m_ctrlSections.SetColumnWidth(0, Rect.Width() / 6);
    130     m_ctrlSections.SetColumnWidth(1, Rect.Width() / 6);
    131     m_ctrlSections.SetColumnWidth(2, Rect.Width() / 6);
    132     m_ctrlSections.SetColumnWidth(3, Rect.Width() / 6);
    133     m_ctrlSections.SetColumnWidth(4, Rect.Width() / 6);
    134     m_ctrlSections.SetColumnWidth(5, Rect.Width() / 6);
    135 }
    136 
    137 BOOL CPEParseDlg::IsPeFileAndGetPePointer(void)
    138 {
    139     BOOL bRet = FALSE;
    140 
    141     m_pDosHeader = (PIMAGE_DOS_HEADER)m_lpBase;
    142     if (IMAGE_DOS_SIGNATURE != m_pDosHeader->e_magic)
    143     {
    144         return bRet;
    145     }
    146 
    147     m_pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)m_lpBase + m_pDosHeader->e_lfanew);
    148     if (IMAGE_NT_SIGNATURE != m_pNtHeaders->Signature)
    149     {
    150         return bRet;
    151     }
    152 
    153     m_pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)&(m_pNtHeaders->OptionalHeader) + m_pNtHeaders->FileHeader.SizeOfOptionalHeader);
    154 
    155     bRet = TRUE;
    156     return bRet;
    157 }
    158 
    159 void CPEParseDlg::ParseBasePe(void)
    160 {
    161     m_strEntryPoint.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.AddressOfEntryPoint);
    162     m_strImageBase.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.ImageBase);
    163     m_strLinkerVersion.Format(_T("%d.%d"), m_pNtHeaders->OptionalHeader.MajorLinkerVersion, m_pNtHeaders->OptionalHeader.MinorLinkerVersion);
    164     m_strSectionNum.Format(_T("%02X"), m_pNtHeaders->FileHeader.NumberOfSections);
    165     m_strFileAlignment.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.FileAlignment);
    166     m_strSectionAlignment.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.SectionAlignment);
    167     UpdateData(FALSE);
    168 }
    169 
    170 void CPEParseDlg::EnumSections(void)
    171 {
    172     m_ctrlSections.DeleteAllItems();
    173 
    174     CString strTemp;
    175     int iSectionNumber = m_pNtHeaders->FileHeader.NumberOfSections;
    176     
    177     for (int i = 0; i < iSectionNumber; ++i)
    178     {
    179         strTemp = m_pSectionHeader[i].Name;
    180         m_ctrlSections.InsertItem(i, strTemp);
    181 
    182         strTemp.Format(_T("%08X"), m_pSectionHeader[i].VirtualAddress);
    183         m_ctrlSections.SetItemText(i, 1, strTemp);
    184 
    185         strTemp.Format(_T("%08X"), m_pSectionHeader[i].Misc.VirtualSize);
    186         m_ctrlSections.SetItemText(i, 2, strTemp);
    187 
    188         strTemp.Format(_T("%08X"), m_pSectionHeader[i].PointerToRawData);
    189         m_ctrlSections.SetItemText(i, 3, strTemp);
    190 
    191         strTemp.Format(_T("%08X"), m_pSectionHeader[i].SizeOfRawData);
    192         m_ctrlSections.SetItemText(i, 4, strTemp);
    193 
    194         strTemp.Format(_T("%08X"), m_pSectionHeader[i].Characteristics);
    195         m_ctrlSections.SetItemText(i, 5, strTemp);
    196     }
    197 }
    198 
    199 void CPEParseDlg::OnBnClickedRadioVa()
    200 {
    201     // TODO: 在此添加控件通知处理程序代码
    202     m_nSelected = 1;
    203     ((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetWindowText(_T(""));
    204     ((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetWindowText(_T(""));
    205     ((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetWindowText(_T(""));
    206     ((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetReadOnly(FALSE);
    207     ((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetReadOnly(TRUE);
    208     ((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetReadOnly(TRUE);
    209 }
    210 
    211 void CPEParseDlg::OnBnClickedRadioRva()
    212 {
    213     // TODO: 在此添加控件通知处理程序代码
    214     m_nSelected = 2;
    215     ((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetWindowText(_T(""));
    216     ((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetWindowText(_T(""));
    217     ((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetWindowText(_T(""));
    218     ((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetReadOnly(TRUE);
    219     ((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetReadOnly(FALSE);
    220     ((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetReadOnly(TRUE);
    221 }
    222 
    223 void CPEParseDlg::OnBnClickedRadioFileoffset()
    224 {
    225     // TODO: 在此添加控件通知处理程序代码
    226     m_nSelected = 3;
    227     ((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetWindowText(_T(""));
    228     ((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetWindowText(_T(""));
    229     ((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetWindowText(_T(""));
    230     ((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetReadOnly(TRUE);
    231     ((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetReadOnly(TRUE);
    232     ((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetReadOnly(FALSE);
    233 }
    234 
    235 void CPEParseDlg::OnBnClickedButtonCalc()
    236 {
    237     // TODO: 在此添加控件通知处理程序代码
    238     m_strImageBase = m_strImageBase.Trim();
    239     if (m_strImageBase.IsEmpty())
    240     {
    241         AfxMessageBox(_T("请先点击查看按钮!"));
    242         return;
    243     }
    244 
    245     CString strPathName;
    246     ((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->GetWindowText(strPathName);
    247     if (strPathName != m_strPathName)
    248     {
    249         AfxMessageBox(_T("你已经更换了PE文件,请先点击查看按钮!"));
    250         return;
    251     }
    252 
    253     DWORD dwAddr = 0;
    254     dwAddr = GetAddr();
    255     int nInNum = GetAddrInSectionNum(dwAddr);
    256     CalcAddr(nInNum, dwAddr);
    257 }
    258 
    259 DWORD CPEParseDlg::GetAddr(void)
    260 {
    261     TCHAR szAddr[10] = {0};
    262     DWORD dwAddr = 0;
    263     switch (m_nSelected)
    264     {
    265     case 1:
    266         GetDlgItemText(IDC_EDIT_VA, szAddr, 10);
    267         HexStrToInt(szAddr, &dwAddr);
    268         break;
    269     case 2:
    270         GetDlgItemText(IDC_EDIT_RVA, szAddr, 10);
    271         HexStrToInt(szAddr, &dwAddr);
    272         break;
    273     case 3:
    274         GetDlgItemText(IDC_EDIT_FILEOFFSET, szAddr, 10);
    275         HexStrToInt(szAddr, &dwAddr);
    276         break;
    277     }
    278 
    279     return dwAddr;
    280 }
    281 
    282 int CPEParseDlg::GetAddrInSectionNum(DWORD dwAddr)
    283 {
    284     int nInNum = 0;
    285     int nSectionNum = m_pNtHeaders->FileHeader.NumberOfSections;
    286     switch (m_nSelected)
    287     {
    288     case 1:
    289         {
    290             DWORD dwImageBase = m_pNtHeaders->OptionalHeader.ImageBase;
    291             for (nInNum = 0; nInNum < nSectionNum; nInNum++)
    292             {
    293                 if (dwAddr >= dwImageBase + m_pSectionHeader[nInNum].VirtualAddress
    294                     && dwAddr <= dwImageBase + m_pSectionHeader[nInNum].VirtualAddress
    295                     + m_pSectionHeader[nInNum].Misc.VirtualSize)
    296                 {
    297                     return nInNum;
    298                 }
    299             }
    300             break;
    301         }
    302     case 2:
    303         for (nInNum = 0; nInNum < nSectionNum; nInNum++)
    304         {
    305             if (dwAddr >= m_pSectionHeader[nInNum].VirtualAddress
    306                 && dwAddr <= m_pSectionHeader[nInNum].VirtualAddress
    307                 + m_pSectionHeader[nInNum].Misc.VirtualSize)
    308             {
    309                 return nInNum;
    310             }
    311         }
    312         break;
    313     case 3:
    314         for (nInNum = 0; nInNum < nSectionNum; nInNum++)
    315         {
    316             if (dwAddr >= m_pSectionHeader[nInNum].PointerToRawData
    317                 && dwAddr <= m_pSectionHeader[nInNum].PointerToRawData
    318                 + m_pSectionHeader[nInNum].SizeOfRawData)
    319             {
    320                 return nInNum;
    321             }
    322         }
    323         break;
    324     }
    325 
    326     return -1;
    327 }
    328 
    329 void CPEParseDlg::CalcAddr(int nInNum, DWORD dwAddr)
    330 {
    331     DWORD dwVa = 0;
    332     DWORD dwRva = 0;
    333     DWORD dwFileOffset = 0;
    334 
    335     switch (m_nSelected)
    336     {
    337     case 1:
    338         dwVa = dwAddr;
    339         dwRva = dwVa - m_pNtHeaders->OptionalHeader.ImageBase;
    340         dwFileOffset = m_pSectionHeader[nInNum].PointerToRawData + (dwRva - m_pSectionHeader[nInNum].VirtualAddress);
    341         break;
    342     case 2:
    343         dwVa = dwAddr + m_pNtHeaders->OptionalHeader.ImageBase;
    344         dwRva = dwAddr;
    345         dwFileOffset = m_pSectionHeader[nInNum].PointerToRawData + (dwRva - m_pSectionHeader[nInNum].VirtualAddress);
    346         break;
    347     case 3:
    348         dwFileOffset = dwAddr;
    349         dwRva = m_pSectionHeader[nInNum].VirtualAddress + (dwFileOffset - m_pSectionHeader[nInNum].PointerToRawData);
    350         dwVa = dwRva + m_pNtHeaders->OptionalHeader.ImageBase;
    351         break;
    352     }
    353 
    354     SetDlgItemText(IDC_EDIT_SECTION, CString(m_pSectionHeader[nInNum].Name));
    355 
    356     CString str;
    357     str.Format(_T("%08X"), dwVa);
    358     SetDlgItemText(IDC_EDIT_VA, str);
    359 
    360     str.Format(_T("%08X"), dwRva);
    361     SetDlgItemText(IDC_EDIT_RVA, str);
    362 
    363     str.Format(_T("%08X"), dwFileOffset);
    364     SetDlgItemText(IDC_EDIT_FILEOFFSET, str);
    365 }
    366 
    367 void CPEParseDlg::HexStrToInt(TCHAR* szAddr, DWORD* pdwAddr)
    368 {
    369     int iLen = lstrlen(szAddr);
    370     *pdwAddr = 0;
    371 
    372     for (int i = 0; i < iLen; i++)
    373     {
    374         if (szAddr[i] >= _T('0') && szAddr[i] <= _T('9'))
    375         {
    376             *pdwAddr = ((*pdwAddr) << 4) | (szAddr[i] - _T('0'));
    377         }
    378         else if (szAddr[i] >= _T('A') && szAddr[i] <= _T('F'))
    379         {
    380             *pdwAddr = ((*pdwAddr) << 4) | (szAddr[i] - _T('A') + 0xA);
    381         }
    382         else if (szAddr[i] >= _T('a') && szAddr[i] <= _T('f'))
    383         {
    384             *pdwAddr = ((*pdwAddr) << 4) | (szAddr[i] - _T('a') + 0xA);
    385         }
    386     }
    387 }
    388 
    389 void CPEParseDlg::OnDestroy()
    390 {
    391     CDialog::OnDestroy();
    392 
    393     // TODO: 在此处添加消息处理程序代码
    394     if (NULL != m_lpBase)
    395     {
    396         UnmapViewOfFile(m_lpBase);
    397     }
    398     
    399     if (NULL != m_hMap)
    400     {
    401         CloseHandle(m_hMap);
    402     }
    403 
    404     if (INVALID_HANDLE_VALUE != m_hFile)
    405     {
    406         CloseHandle(m_hFile);
    407     }
    408 }
    409 
    410 HBRUSH CPEParseDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    411 {
    412     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    413 
    414     // TODO:  在此更改 DC 的任何属性
    415     //if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC || nCtlColor == CTLCOLOR_EDIT)
    416     //{
    417     //    pDC->SetBkMode(TRANSPARENT);
    418     //    return CreateSolidBrush(RGB(0x2F, 0x4F, 0x4F));
    419     //}
    420 
    421     // TODO:  如果默认的不是所需画笔,则返回另一个画笔
    422     return hbr;
    423 }
    424 
    425 void CPEParseDlg::OnBnClickedButtonAddsection()
    426 {
    427     // TODO: 在此添加控件通知处理程序代码
    428     m_strImageBase = m_strImageBase.Trim();
    429     if (m_strImageBase.IsEmpty())
    430     {
    431         AfxMessageBox(_T("请先点击查看按钮!"));
    432         return;
    433     }
    434 
    435     CString strPathName;
    436     ((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->GetWindowText(strPathName);
    437     if (strPathName != m_strPathName)
    438     {
    439         AfxMessageBox(_T("你已经更换了PE文件,请先点击查看按钮!"));
    440         return;
    441     }
    442 
    443     TCHAR szSectionName[8] = {0};
    444     int nSectionSize = 0;
    445 
    446     GetDlgItemText(IDC_EDIT_SECTIONNAME, szSectionName, 8);
    447     nSectionSize = GetDlgItemInt(IDC_EDIT_SECTIONSIZE, FALSE, TRUE);
    448 
    449     AddSection(szSectionName, nSectionSize);
    450 }
    451 
    452 void CPEParseDlg::AddSection(TCHAR* szSectionName, int nSectionSize)
    453 {
    454     int nSectionNum = m_pNtHeaders->FileHeader.NumberOfSections;
    455     DWORD dwFileAlignment = m_pNtHeaders->OptionalHeader.FileAlignment;
    456     DWORD dwSectionAlignment = m_pNtHeaders->OptionalHeader.SectionAlignment;
    457 
    458     PIMAGE_SECTION_HEADER pTempSection = m_pSectionHeader + nSectionNum;
    459 
    460     int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)szSectionName, -1, NULL, 0, NULL, NULL);
    461     char *pszSectionNameA = new char[nLen];
    462     WideCharToMultiByte(CP_ACP, 0, szSectionName, -1, pszSectionNameA, nLen * sizeof(char), NULL, NULL);
    463     //拷贝节名
    464     strncpy((char*)(pTempSection->Name), pszSectionNameA, 7);
    465     delete[] pszSectionNameA;
    466     pszSectionNameA = NULL;
    467     //节的内存大小
    468     pTempSection->Misc.VirtualSize = AlignSize(nSectionSize, dwSectionAlignment);
    469     //节的内存起始位置
    470     pTempSection->VirtualAddress = m_pSectionHeader[nSectionNum - 1].VirtualAddress 
    471         + AlignSize(m_pSectionHeader[nSectionNum - 1].Misc.VirtualSize, dwSectionAlignment);
    472     //节的文件大小
    473     pTempSection->SizeOfRawData = AlignSize(nSectionSize, dwFileAlignment);
    474     //节的文件起始位置
    475     pTempSection->PointerToRawData = m_pSectionHeader[nSectionNum - 1].PointerToRawData
    476         + AlignSize(m_pSectionHeader[nSectionNum - 1].SizeOfRawData, dwFileAlignment);
    477     //修正节数量
    478     m_pNtHeaders->FileHeader.NumberOfSections++;
    479     //修正映像大小
    480     m_pNtHeaders->OptionalHeader.SizeOfImage += pTempSection->Misc.VirtualSize;
    481     //填充内存映射
    482     FlushViewOfFile(m_lpBase, 0);
    483     //添加节数据
    484     AddSectionData(pTempSection->SizeOfRawData);
    485 
    486     CString str;
    487     str.Format(_T("%02X"), m_pNtHeaders->FileHeader.NumberOfSections);
    488     ((CEdit*)GetDlgItem(IDC_EDIT_SECTIONNUM))->SetWindowText(str);
    489     EnumSections();
    490 }
    491 
    492 DWORD CPEParseDlg::AlignSize(int nSectionSize, DWORD dwAlignment)
    493 {
    494     int nSize = nSectionSize;
    495     if (nSize % dwAlignment != 0)
    496     {
    497         nSectionSize = (nSize / dwAlignment + 1) * dwAlignment;
    498     }
    499 
    500     return nSectionSize;
    501 }
    502 
    503 void CPEParseDlg::AddSectionData(int nSectionSize)
    504 {
    505     PBYTE pByte = NULL;
    506     pByte = (PBYTE)malloc(nSectionSize);
    507     ZeroMemory(pByte, nSectionSize);
    508 
    509     DWORD dwNum = 0;
    510     SetFilePointer(m_hFile, 0, 0, FILE_END);
    511     WriteFile(m_hFile, pByte, nSectionSize, &dwNum, NULL);
    512     FlushFileBuffers(m_hFile);
    513 
    514     free(pByte);
    515 }

    下载地址如下:

    http://pan.baidu.com/s/1hqBR06S

  • 相关阅读:
    主机不能访问虚拟机CentOS中的站点
    linux安装redis
    java获去json所有对象
    Java nio和io
    [shell基础]——if/for/while/until/case 语句
    [shell基础]——整数比较;字符串比较;文件测试;逻辑测试符
    [shell基础]——数组
    [shell基础]——I/O重定向
    [shell基础]——tr命令
    [shell基础]——split命令
  • 原文地址:https://www.cnblogs.com/qiyueliuguang/p/3544144.html
Copyright © 2020-2023  润新知