備忘録

備忘録

C++でHTTP(S)でGET/POSTする(cpprestsdk の使い方)

Ⅰ. はじめに

.NET系 であれば WebClient や HttpClient が標準である為、
追加のライブラリ無しでHTTPをモダンかつ簡単に扱うことができます。

しかし、C++にはそのような物が標準ではありません。
ライブラリを探した結果、Microsoft社が作成しているC++ RESET SDK(cpprestsdk)にたどり着きました。

Ⅱ. なぜ「C++ RESET SDK(cpprestsdk)」を選んだのか

Ⅲ. インストール方法

※NuGetで配布されている物はダイナミックリンクライブラリのみ。
スタティックリンクライブラリが欲しい人はこちら

Install-Package cpprestsdk
sudo apt-get install libcpprest-dev
brew install cpprestsdk

その他は公式を参照して下さい。
https://github.com/Microsoft/cpprestsdk/wiki/Getting-Started-Tutorial#getting-the-c-rest-sdk

Ⅳ. GET(同期)

// #pragma comment(lib, "crypt32.lib")
// #pragma comment(lib, "bcrypt.lib")
// #pragma comment(lib, "winhttp.lib")
#include <cpprest/http_client.h>

int main()
{
  web::http::client::http_client client(L"http://example.com/");
  auto response = client.request(web::http::methods::GET).get();
  if (response.status_code() == web::http::status_codes::OK)
  {
    // レスポンスを文字列として取得後、標準出力する
    auto body = response.extract_string().get();
    std::wcout << body << std::endl;
  }
  return 0;
}

Ⅴ. GET(非同期)

#include <Windows.h>
#include <iostream>
#include <cpprest/http_client.h>

using namespace web;
using namespace web::http;
using namespace web::http::client;

pplx::task<void> Get()
{
  return pplx::create_task([]
  {
    // proxyあり
    // auto config = http_client_config();
    // config.set_proxy(web_proxy(utility::conversions::to_string_t("http://127.0.0.1:8080")));
    // http_client client(L"https://jsonplaceholder.typicode.com/posts/1", config);

    http_client client(L"https://jsonplaceholder.typicode.com/posts/1");
    return client.request(methods::GET);
  }).then([](http_response response)
  {
    if (response.status_code() == status_codes::OK)
    {
      // レスポンスを文字列として取得後、標準出力する
      // auto body = response.extract_string();
      // std::wcout << body.get().c_str() << std::endl;

      // レスポンスをJSONとして解析する
      return response.extract_json();
    }
  }).then([](json::value json)
  {
    // タイトルだけ取得する
    std::wcout << json[L"title"].as_string() << std::endl;
  });
}

int main()
{
  // コマンドプロンプトの文字コードをUTF-8に設定する
  SetConsoleOutputCP(CP_UTF8);

  try
  {
    Get().wait();
  }
  catch (const std::exception &e)
  {
    std::cout << "Error " << e.what() << std::endl;
  }

  return 0;
}
実行結果

f:id:kagasu:20171007190436p:plain

Ⅵ. POST(JSON)(非同期)

#include <Windows.h>
#include <iostream>
#include <cpprest/http_client.h>

using namespace web;
using namespace web::http;
using namespace web::http::client;

pplx::task<int> Post()
{
  return pplx::create_task([]
  {
    json::value postData;

    auto sex = utility::conversions::to_string_t("man");
    postData[L"user_info"][L"name"] = json::value::string(L"user001");
    postData[L"user_info"][L"sex"] = json::value::string(sex);
    postData[L"user_info"][L"age"] = json::value::number(20);

    // proxyあり
    // auto config = http_client_config();
    // config.set_proxy(web_proxy(utility::conversions::to_string_t("http://127.0.0.1:8080")));
    // http_client client(L"http://localhost/api", config);
    http_client client(L"http://localhost/api");
    return client.request(methods::POST, L"", postData.serialize(), L"application/json");
  }).then([](http_response response)
  {
    if (response.status_code() == status_codes::OK)
    {
      //auto body = response.extract_string();
      //std::wcout << body.get().c_str() << std::endl;
      //std::cout << response.extract_json() << std::endl;
      return response.extract_json();
    }
  }).then([](json::value json)
  {
    // リザルトコードを返す
    return json[L"result"].as_integer();
  });
}

int main()
{
  // コマンドプロンプトの文字コードをUTF-8に設定する
  SetConsoleOutputCP(CP_UTF8);

  try
  {
    auto result = Post().wait();
    std::cout << "Result = " << result << std::endl;
  }
  catch (const std::exception &e)
  {
    std::cout << "Error " << e.what() << std::endl;
  }

  return 0;
}
実行結果

f:id:kagasu:20171007190519p:plain

Ⅶ. POST(form-urlencoded)

http_client client(L"http://localhost/api");
client.request(methods::POST, L"", uri::encode_uri(L"name=田中太郎&age=20"), L"application/x-www-form-urlencoded");
実行結果

省略

その他

Ubuntuコンパイルする時
$ g++ a.cpp -std=c++14 -lcpprest -lboost_system -lssl -lcrypto

OpenSSLをWindowsでビルドする方法

Ⅰ. はじめに

タイトルの通り「OpenSSLをWindowsでビルドする方法」です。
コンパイル済みライブラリだけ欲しい人はこちら

Ⅱ. 環境(必要なもの)

Visual Studio 2017 Community (C++)
PerlActivePerl を利用しました)
・OpenSSL 1.0.2l のソースコード
https://www.openssl.org/source/

Ⅲ. やり方

1. 「VS 2017用x86_x64 Cross Tools コマンドプロンプト」を起動する

2. 以下のコマンドを実行
cd c:\openssl\openssl-1.0.2l
perl Configure no-asm --prefix=..\x64 VC-WIN64A
ms\do_win64a.bat
nmake -f ms\ntdll.mak install
3. 実行結果

f:id:kagasu:20171003143201p:plain

.NET 難読化ツール「Obfuscar」の使い方

Ⅰ. はじめに

無料で利用できる難読化ツール Obfuscar の使い方です。
GitHubソースコードが公開されています。
https://github.com/lextm/obfuscar

Ⅱ. 使い方

1. NuGetから必要なライブラリをインストールします
Install-Package Obfuscar
2. プロジェクトに適当な名前のXMLファイルを作成します

※この記事では「ObfuscarConfig.xml」とします。

f:id:kagasu:20171002195732p:plain

3. ObfuscarConfig.xmlを編集します

各値の意味は公式ドキュメントを参照して下さい。
http://docs.obfuscar.com/en/latest/getting-started/configuration.html#table-of-settings

<?xml version="1.0" encoding="utf-8"?>
<Obfuscator>
  <Var name="InPath" value=".\" />
  <Var name="OutPath" value=".\Obfuscar" />
  
  <Var name="KeepPublicApi" value="false" />
  <Var name="HidePrivateApi" value="true" />
  
  <Module file="$(InPath)\bin\Debug\ObfuscarTest.exe" />
  <!--<Module file="$(InPath)\bin\Release\ObfuscarTest.exe" />-->
  <!--<Module file="$(InPath)\HogeLibrary.dll" />-->
</Obfuscator>
4.ビルド後イベントを変更します
cd $(ProjectDir)
$(SolutionDir)packages\Obfuscar.2.2.9\tools\Obfuscar.Console.exe ObfuscarConfig.xml


5. ビルドを実行します
6. 「Obfuscar」フォルダに難読化されたexeが作成されます

f:id:kagasu:20171002200853p:plain

SYSTEM権限でアプリケーションを実行する方法

Ⅰ. はじめに

タイトルの通り「NT AUTHORITY\SYSTEM」でアプリケーションを実行する方法です。

f:id:kagasu:20170927190901p:plain

Ⅱ. やり方

やり方は3つあります。

1. AprelTech社のRunAsSystemを使う方法

https://www.apreltech.com/Free/How_to_run_as_system_user

非常にわかりやすいGUIがあるので簡単です。
f:id:kagasu:20170927190924p:plain

2. PsToolsのPsExecを使う方法

「-s オプション」を付けるとSYSTEM権限で実行できます。

管理者権限で実行する必要があります。

PsExec.exe -s cmd.exe

※稀に以下のエラーが出力されSYSTEM権限で実行できないPCが存在します。
治し方は見つかりませんでした。

Error establishing communication with PsExec service on [ComputerName]:
The network path was not found.
3. Michael Badichi氏が公開しているコードを利用する方法

https://github.com/michaelbadichi/RunAsSystem

日本語の詳しい情報はこちらにあります。
http://eternalwindows.jp/security/securitycontext/securitycontext13.html

管理者権限で実行する必要があります。

RunAsSystem.exe cmd.exe

Administrator アカウントの有効化、無効化を行う方法

有効化

コマンドプロンプトで以下のコマンドを実行する

net user administrator /active:yes

無効化

コマンドプロンプトで以下のコマンドを実行する

net user administrator /active:no