備忘録

備忘録

UnrealEngineでコンソールログを表示する方法

Ⅰ. はじめに

タイトルの通り「UnrealEngineでコンソールログを表示する方法」です。

Ⅱ. やり方

1. Engine.iniを編集する
[Core.Log]
Global=VeryVerbose
;Global=warning
;LogTemp=VeryVerbose
2. 引数に-Logを加えて起動する
MyGame.exe -Log

実行結果

f:id:kagasu:20211112153831p:plain

Windowsでプロセスを終了する方法

Ⅰ. はじめに

タイトルの通り「Windowsでプロセスを終了する方法」です。

Ⅱ. 方法

1. msvcrt.abort
#include <Windows.h>

int main() {
  abort();
  return 0;
}
2. msvcrt.exit
#include <Windows.h>

int main() {
  exit(0);
  return 0;
}
3. kernel32.ExitProcess
#include <Windows.h>

int main() {
  ExitProcess(0);
  return 0;
}
4. ntdll.RtlExitUserProcess
#include <Windows.h>
#pragma comment(lib, "ntdll.lib")

// https://doxygen.reactos.org/d6/d9e/include_2reactos_2wine_2winternl_8h.html#ac53be5d52ae8419ef124f65379e4d35b
extern "C" NTSYSAPI void DECLSPEC_NORETURN WINAPI RtlExitUserProcess(ULONG);

int main() {
  RtlExitUserProcess(0);
  return 0;
}
5. ntdll.NtTerminateProcess (ZwTerminateProcess)
#include <Windows.h>
#pragma comment(lib, "ntdll.lib")

// https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FProcess%2FNtTerminateProcess.html
extern "C" NTSYSAPI NTSTATUS NTAPI NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus);

int main() {
  NtTerminateProcess(GetCurrentProcess(), 0);
  return 0;
}
6. syscall

Native.asm

.code

NtTerminateProcess proc
  mov r10, rcx
  mov eax, 2Ch
  syscall
  ret
NtTerminateProcess endp

end

Source.cpp

#include <Windows.h>

// https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FProcess%2FNtTerminateProcess.html
extern "C" NTSYSAPI NTSTATUS NTAPI NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus);

int main() {
  NtTerminateProcess(GetCurrentProcess(), 0);
  return 0;
}

Ⅲ. 方法(ウィンドウ系)

1. user32.PostQuitMessage
#include <Windows.h>

int main() {
  PostQuitMessage(0);
  return 0;
}
2. win32u.NtUserCallOneParam
#include <Windows.h>
#pragma comment(lib, "win32k.lib")

// ライブラリディレクトリに以下を追記する
// $(WindowsSDK_LibraryPath)\..\km\x64

extern "C" DWORD NTAPI __win32kstub_NtUserCallOneParam(DWORD Param, DWORD Routine);

int main() {
  __win32kstub_NtUserCallOneParam(0, 0);
  return 0;
}
3. syscall
  • syscall番号 0x1002(OSバージョンに依存します)
  • プログラム省略

Ⅳ. その他

1. 呼び出しツリー

msvcrt.abort → msvcrt.exit → kernel32.ExitProcess → ntdll.RtlExitUserPRocess → ntdll.NtTerminateProcess (ZwTerminateProcess) → syscall

2. 呼び出しツリー(ウィンドウ系)

user32.PostQuitMessage → win32u.NtUserCallOneParam → syscall

漢字をひらがな、漢字をカタカナに変換する方法

Ⅰ. はじめに

タイトルの通り「漢字をひらがな、漢字をカタカナに変換する方法」です。

Ⅱ. やり方

1. 必要なパッケージをインストールする

MeCab

dotnet add package MeCab.DotNet --version 0.0.40

Kanaxs.cs
https://archive.md/YyDNR

2. サンプルプログラムを書く
using MeCab;

namespace Test
{
  class Program
  {
    /// <summary>
    /// 漢字→カタカナ
    /// </summary>
    static string KanjiToKatakana(string str)
    {
      var sb = new StringBuilder();
      using var tagger = MeCabTagger.Create();

      foreach (var node in tagger.ParseToNodes(str))
      {
        if (node.CharType > 0)
        {
          var features = node.Feature.Split(',');
          if (features.Length > 8)
          {
            var yomiKatakana = features[8];
            sb.Append(yomiKatakana);
          }
        }
      }

      return sb.ToString();
    }

    /// <summary>
    /// 漢字→ひらがな
    /// </summary>
    static string KanjiToHiragana(string str)
    {
      var sb = new StringBuilder();
      using var tagger = MeCabTagger.Create();

      foreach (var node in tagger.ParseToNodes(str))
      {
        if (node.CharType > 0)
        {
          var features = node.Feature.Split(',');
          if (features.Length > 8)
          {
            var yomiKatakana = features[8];
            var yomiHiragana = CSharp.Japanese.Kanaxs.Kana.ToHiragana(yomiKatakana);
            sb.Append(yomiHiragana);
          }
        }
      }

      return sb.ToString();
    }

    static void Main(string[] args)
    {
      Console.WriteLine(KanjiToKatakana("私の名前は田中太郎です。宜しくお願いします。"));
      Console.WriteLine(KanjiToHiragana("私の名前は田中太郎です。宜しくお願いします。"));
    }
  }
}

実行結果

ワタシノナマエワタナカタローデス。ヨロシクオネガイシマス。
わたしのなまえわたなかたろーです。よろしくおねがいします。

QEMUでUEFIを利用する方法

Ⅰ. はじめに

タイトルの通り「QEMUUEFIを利用する方法」です。

Ⅱ. 環境

Ubuntu 20.04.1 LTS

Ⅲ. やり方

1. KVMが利用できるか確認する(オプション)
apt install cpu-checker
kvm-ok
2. QEMUをインストールする
apt install qemu qemu-utils qemu-system-x86

# KVMが利用できる場合
# apt install qemu qemu-utils qemu-kvm
3. OVMFをインストールする
apt install ovmf
4. 起動する
qemu-system-x86_64 \
#  -enable-kvm \
  -bios OVMF.fd \
#  -boot menu=on \
  -vnc 127.0.0.1:1
5. SSHトンネリング接続する(オプション)

※1番目のディスプレイに対するVNCポートが5901です。
※7777は特に意味はありません。

ssh -L 7777:127.0.0.1:5901 root@10.0.0.1

実行結果

f:id:kagasu:20211028164641p:plain

その他

Q. UEFIの設定を保存するにはどうすればいいですか?

A. OVMF.fdをコピーして利用する。

cp /usr/share/ovmf/OVMF.fd /root/OVMF.fd
qemu-system-x86_64 \
  -bios /root/OVMF.fd

C++で.NETのBinaryReaderのような事をする方法

Ⅰ. はじめに

タイトルの通り「C++で.NETのBinaryReaderのような事をする方法」です。

Ⅱ. サンプルプログラム

#include <iostream>
#include <string>

class BinaryReader
{
private:
  uint8_t *p;
  
public:
  BinaryReader(uint8_t *data)
  {
    this->p = data;
  }

  template<typename T>
  T read()
  {
    auto p = reinterpret_cast<T*>(this->p);
    this->p += sizeof(T);
    return *p;
  }

  template<typename T>
  std::string readString()
  {
    auto length = *reinterpret_cast<T*>(this->p);
    this->p += sizeof(T);

    std::string str(reinterpret_cast<char*>(this->p), length);
    this->p += length;

    return str;
  }
};

int main() {
  uint8_t data[] = {
    0x01, 0x00, // ID(2バイト)
    0x06, 0x00, 0x00, 0x00, // Nameの長さ(4バイト)
    0x74, 0x61, 0x6e, 0x61, 0x6b, 0x61, // Name(tanaka)
    0x14 // Age(1バイト)
  };

  BinaryReader reader(data);

  auto id = reader.read<uint16_t>();
  auto name = reader.readString<uint32_t>();
  auto age = reader.read<uint8_t>();

  std::printf("Id: %d\n", id);
  std::printf("Name: %s\n", name.c_str());
  std::printf("Age: %d\n", age);

  return 0;
}

実行結果

Id: 1
Name: tanaka
Age: 20