link もっと前
   2020年 7月 7日 -
      2020年 6月 28日  
link もっと後

link 未来から過去へ表示(*)
link 過去から未来へ表示

日々

link permalink

link 編集する

ELF バイナリで SEGV その 2 - 64 バイト

昨日(2020年 7月 4日の日記参照)は SEGV する ELF バイナリサイズを 92 バイトまで削ることができました。

その後、色々弄っていて見つけたのですが、プログラムヘッダの type を NULL にしておけば、ファイルサイズやオフセットがめちゃくちゃでも execve は文句を言わないっぽいみたいです。

ELF ヘッダの e_ident の後半 8バイトは 0(前半を書き換えると ELF と認識されなくなります)なので、この部分をプログラムヘッダだよ、と指定すれば type NULL に解釈されます。

これで 64 バイト、つまり ELF ヘッダしかない実行ファイルができました。何の役にも立たないですけどね……。

SEGV するバイナリ、64バイト版
$ ls -la a.out

-rwxrwxr-x+ 1 katsuhiro katsuhiro 64 Jul  3 06:39 a.out


SEGV する 64 バイトバイナリ、ELF ヘッダ


SEGV する 64 バイトバイナリ、プログラムヘッダ

これ以上 1 バイトでも削ると ELF ヘッダの長さを下回るため、ELF バイナリとして成立しません。よって 64 バイトが最短だと思いますが、私が気づいていない裏技があるかもしれません。

SEGV する 64 バイトバイナリの検証

このファイルを実行してみると、システムコール execve がエラーを返さないで進むので、ELF ファイルとして認識してもらえているようです。

SEGV する 64 バイトバイナリ、実行
$ strace ./a.out

execve("./a.out", ["./a.out"], 0x7ffedf7dfa90 /* 47 vars */) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x400000001} ---
+++ killed by SIGSEGV +++
Segmentation fault
SEGV する 64 バイトバイナリ、readelf
$ readelf -a a.out
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400000001
  Start of program headers:          8 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  NULL           0x00000001003e0002 0x0000000400000001 0x0000000000000008
                 0x0000000000000000 0x0038004000000000         0x1
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not curr
ently supported.
Dynamic symbol information is not available for displaying symbols.
No version information found in this file.

一応 readelf でも読めますが、プログラムヘッダのオフセットやアドレスはめちゃくちゃです。

[編集者: すずき]
[更新: 2020年 7月 5日 21:07]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link permalink

link 編集する

ELF バイナリで SEGV その 1 - 92 バイト

昨日(2020年 7月 3日の日記参照)試したところによると、C 言語は 0 文字で SEGV するプログラムを書けました。

では、出力されたバイナリだと最短はいくつでしょうか?とりあえずベースとして C 言語の 0 文字 SEGV プログラムの出力を見ます。

0 文字で SEGV のバイナリサイズ
$ gcc -nostdlib a.c

/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000

$ ls -la a.out

-rwxr-xr-x 1 katsuhiro katsuhiro 9528 Jul  3 04:11 a.out

なんと 9KB もあります。readelf で見るとダイナミックリンカー関連のシンボルが含まれているようなので、static オプションを付けてダイナミックリンカー関連のシンボルを消します。

0 文字で SEGV のバイナリサイズ、static 版
$ echo -n  > a.c && gcc -nostdlib -static a.c

/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000

$ ls -la a.out

-rwxr-xr-x 1 katsuhiro katsuhiro 968 Jul  3 04:12 a.out

$ strace ./a.out

execve("./a.out", ["./a.out"], 0x7ffc92c2b390 /* 46 vars */) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x401000} ---
+++ killed by SIGSEGV +++
Segmentation fault

ログが大量に出るはずの strace も、わずか 1行しかログが出ません。何もしないバイナリにも関わらず a.out のサイズは 1KB 近くあります。

ツールでバイナリを削る

お手軽なバイナリのダイエットとして、実行に不要なセクションを strip します。

SEGV するバイナリ、strip する
$ strip -R ".note.gnu.build-id" -R ".comment" a.out

$ ls -la a.out
-rwxr-xr-x 1 katsuhiro katsuhiro 376 Jul  3 04:18 a.out

それでも 376 バイト。まだでかいですね。

手でバイナリを削る

この 376 バイトのファイルを元にして、バイナリを手で削ります。加工の方針としては、

  • ELF ヘッダ(64バイト)とプログラムヘッダ(56バイト)を一部重ねる(-28バイト)
  • 不要なプログラムヘッダ 2つを消す(-56 x 2バイト)
  • セクションヘッダを消す(-64 x 2バイト)
  • .shstrtab セクションを消す(-16バイト)
  • ELF ヘッダの辻褄を合わせる

結果 92 バイトになりました。

SEGV するバイナリ、手で削る
$ ls -la a.out

-rwxrwxr-x+ 1 katsuhiro katsuhiro 92 Jul  3 05:43 a.out


SEGV する 92 バイトバイナリ、ELF ヘッダ


SEGV する 92 バイトバイナリ、プログラムヘッダ

もっとアグレッシブに ELF ヘッダとプログラムヘッダを重ねれば、64 バイトにできるかもしれません。

SEGV する 92 バイトバイナリの検証

このファイルを実行してみると、システムコール execve がエラーを返さないで進むので、ELF ファイルとして認識してもらえているようです。

SEGV する 92 バイトバイナリ、実行
$ strace ./a.out

execve("./a.out", ["./a.out"], 0x7fff2b4f74a0 /* 47 vars */) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x400000001} ---
+++ killed by SIGSEGV +++
Segmentation fault
SEGV する 92 バイトバイナリ、readelf
$ readelf -a a.out

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400000001
  Start of program headers:          36 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  NULL           0x0000000000000000 0x0000000100380040 0x0000000000000000
                 0x0000000000000000 0x0000000000000000         0x1000
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Dynamic symbol information is not available for displaying symbols.
No version information found in this file.

一応 readelf でも読めますし、そこそこ真っ当なファイルをキープできていると思います。

[編集者: すずき]
[更新: 2020年 7月 5日 21:06]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link permalink

link 編集する

C 言語で SEGV

SEGV を出すのが Twitter で流行しているみたいなので、少し考えてみました。Twitter で見かけたのは、*a;main(){*a=0;}(16文字)です。最適化オプションにもよりますが、異常なアドレスへの mov か、未定義命令 ud2 が出力されて SEGV します。

16文字で SEGV
$ echo -n '*a;main(){*a=0;}' > a.c && gcc a.c

a.c:1:1: warning: data definition has no type or storage class
    1 | *a;main(){*a=0;}
      | ^
a.c:1:2: warning: type defaults to 'int' in declaration of 'a' [-Wimplicit-int]
    1 | *a;main(){*a=0;}
      |  ^
a.c:1:4: warning: return type defaults to 'int' [-Wimplicit-int]
    1 | *a;main(){*a=0;}
      |    ^~~~

$ ./a.out

Segmentation fault

ただ SEGV するだけで良ければ、main のアドレスを .text ではないアドレスにすれば良いので、main;(5 文字)でも、達成できます。

5文字で SEGV
$ echo -n 'main;' > a.c && gcc a.c

a.c:1:1: warning: data definition has no type or storage class
    1 | main;
      | ^~~~
a.c:1:1: warning: type defaults to 'int' in declaration of 'main' [-Wimplicit-int]

$ ./a.out

Segmentation fault

この例は main を関数ではなく変数として定義し、main を bss セクションに配置します。最近の Linux ならばデータが置かれているセグメントは実行禁止にするはずなので、main が指すデータが何であろうと、ジャンプした瞬間に SEGV します。

趣旨とは外れますが SEGV を避けて正常終了させたければ、

SEGV したくない場合
$ echo -n 'main=0xc3;' > a.c && gcc -z execstack a.c

a.c:1:1: warning: data definition has no type or storage class
    1 | main=0xc3;
      | ^~~~
a.c:1:1: warning: type defaults to 'int' in declaration of 'main' [-Wimplicit-int]

$ ./main3.out

(SEGV しない)

変数 main が指す位置に retq 命令(0xc3)を置いて、-z execstack オプションでデータ領域を実行可能にしています。attribute で .text 領域に置いても実行できますが、そんなことするくらいなら main() 関数を書いた方が短いです。

これが最短か?

変化球を使ってよければ 0 文字で SEGV できます。nostdlib オプションを使います。

0 文字で SEGV
$ echo -n > a.c && gcc -nostdlib a.c

/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000

$ ./a.out

Segmentation fault

GNU ld(他のリンカーでも同じだと思いますけど)は ELF のエントリアドレスに _start というシンボルのアドレスを使います。通常は crt.o など、リンク時に自動的に追加されるオブジェクトが _start を定義しますが、nostdlib オプションにより crt.o がリンクされなくなって、_start は未定義になります。

すると ld は _start を適当なアドレスに設定(上記の例では 0x1000 に)します。当然 _start が指すアドレスにコードはありませんから、実行するとクラッシュします。

[編集者: すずき]
[更新: 2020年 7月 5日 18:58]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link permalink

link 編集する

Steam の秘密の実績を暴く方法

Steam の買い物カートの中身一覧を見る方法を探していたんですが、全くわかりませんでした。だいぶ彷徨いましたが、未だトップ画面からカートを見る方法はわからないままです。Steam は本当に UI がひどい。Amazon を見習ってくれ……。

その際に副産物として、秘密の実績を確認する方法を見つけたのでメモしておきます。

  • Steam のウインドウ
  • ユーザー名のタブ
  • プロフィール
  • 最近プレイした全てのゲーム
  • すべてのゲーム

と辿ると自分が所持しているゲームの一覧が出ますから、実績を見たいゲームの

  • データを表示
  • グローバル実績

と辿ると全ての実績が表示されます。


個人のプレイデータでは秘密の実績と表示される


グローバルプレイデータでは秘密の実績も全て表示される

秘密の実績の意味とは一体……??

[編集者: すずき]
[更新: 2020年 7月 2日 03:27]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link permalink

link 編集する

STATIONflow ランク 100

STATIONflow のランクが 100 になりました。何か実績と紐づいているかなと思いましたが、特に何も起きませんでした。しょんぼり。


ランク 100

普通のマップだと重いし、時間も掛かりすぎてやってられないので、専用の軽量マップを作ってひたすら待ちました。それでも相当時間が掛かります。普通に遊ぶ分にはランク 50 で十分ですね。

わかったこと

STATIONflow でランク 100 にする途中でいくつかわかったことがありました。

集客レベル
途中で出入口と乗り場の集客レベルがカンストし、変化もやることもなくなります。実績解除に必要なランク 50 以降はほぼ無意味です。
集客レベルの上がる余地は最大 132(※)なので、ランク 100 まで上がり続けるかと思いきや、ランク 1 上がるごとに集客レベルが 2〜4 くらい上がるので、だいたいランク 60 くらいでカンストします。
評価収入
ランクとは無関係で、出入口と乗り場の集客レベルの合計に依存するようです。出入口と乗り場を最大数作り、集客レベルを全て最大にして、ランク A+ を取ったときが 540,000 でした。おそらくこれが最大値です。

ランク 100 まで行ってもまだ取れない実績が残っていて(ラッキーセブン、トウキョウ)、なかなか気が遠くなるゲームです。

(※)出入口が 6 x 9 = 54、乗り場が 6 x 2 = 12、集客レベルは 2段階上がるため (54 + 12) x 2 = 132 です。

実績の typo

STATIONflow の実績に typo がありました。


8000?九千?

漢字だけ間違ってます。惜しい……!

[編集者: すずき]
[更新: 2020年 7月 1日 22:20]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link permalink

link 編集する

STATIONflow の駅の評価

以前(2020年 5月 28日の日記参照)STATIONflow で速度 3 にすると駅の評価が下がることをお伝えしましたが、若干間違っていて「画面の処理落ちで評価が下がる」方が実態に近そうです。

速度 2 で A+ 評価の駅を使って実験したところ、ノート PC のクロック周波数を低くするだけで、駅の評価が A に下がりました。

駅の評価と見せかけて、実はマシンの評価も入ってるんでしょうか?余計なお世話なので、勘弁してくれよ。

[編集者: すずき]
[更新: 2020年 6月 30日 23:12]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link permalink

link 編集する

ノート PC の発熱を抑える方法

ノート PC でゲームをしていると、筐体が焼けそうなほど熱くなり、キーボードまで熱くなってキーを打つのが辛いです。

発熱の原因はグラフィックスチップですが、どうも CPU も無罪ではないらしく、TurboBoost を無効にするとややマシになることがわかりました。

私のマシンでは「電源オプション」 - 「プロセッサの電源管理」 - 「最大のプロセッサの状態」にて、87%以下にすると TurboBoost が OFF になりました。


最大のプロセッサの状態を 87%に設定

下記は 87%設定(1.49GHz)と 88%設定(3.38GHz)にしたときの CPU 動作周波数の変化です。


87%に設定したときの CPU 動作周波数は 1.49GHz


88%に設定したときの CPU 動作周波数は 3.38GHz

当然ながら 1.49GHz と 3.38GHz では性能に天と地ほどの差があって、1.49GHz だと STATIONflow の画面はめちゃくちゃカクつきます。

しかしシミュレーションゲームでは、待っているだけの時もありますし、常に爆熱で動いてくれる必要はありません。TurboBoost を任意に OFF にできるのは非常に便利です。

設定と動作周波数の関係一覧

CPU のクロック周波数の上限は何段階かあるようなので、変化点を調べました。

  • 〜60%: 0.99GHz
  • 〜65%: 1.10GHz
  • 〜71%: 1.19GHz
  • 〜76%: 1.30GHz
  • 〜82%: 1.39GHz
  • 〜87%: 1.49GHz
  • 〜100%: 3.36GHz

こんな感じでした。Core i5-8250U はベース周波数 1.6GHz、ブースト周波数 3.4GHz なのにベース周波数である 1.6GHz に張り付く設定は存在しません。謎です。

タスクマネージャーに「基本速度 1.8GHz」と表示されているのも謎です。どこから 1.8GHz 出てきた……??

[編集者: すずき]
[更新: 2020年 6月 30日 23:07]

コメント一覧

  • hdk 
    Athlon 5350 (2.05GHz) をUEFI Setupで上限1.1GHzに設定して使っているのですが、基本速度のところにはちゃんと1.10 GHzと出ています。1.80 GHzとは...  
    (2020年06月30日 23:55:23)
  • すずき 
    うちのマシンは基本速度が取得できてないんですかねえ?BIOS は 1.6GHz とおっしゃっているんですが。
    仮に Windows が言ってる 1.8GHz が正解だとしても、1.8GHz に張り付く設定もないので、やっぱり謎は残ります。 
    (2020年07月01日 11:18:21)
open/close この記事にコメントする



link permalink

link 編集する

STATIONflow まさかの実績解除方法

STATIONflow のしょうもない小技 その 2 です。

実績の解除が非常に難しい「エレベスト」や「効率の鬼」のような難しい実績が、超簡単に取れる方法です。

例えば、エレベストの条件は「駅ランク 20 以上で階段とエスカレーターを設置せずに A+ 評価」です。前回(2020年 6月 27日の日記参照)お伝えした通り、エレベーターと通勤客の変な挙動が合わさって、まともにやるとかなり難しいです。

しかし STATIONflow の実績判定は甘々で「00:00 になった瞬間」しか見ません。従って、

  • ランク 20、A+ 評価の駅を作る(階段、エスカレーター使用可)
  • 23:50 になったら時間を止める
  • 階段、エレベーターを全て破壊する
  • 時間を再始動させ 00:00 を迎える

これだけで達成できます。正直、こんな低レベルな小細工が通じると思わなかったので、逆にびっくりしました……。

類似した実績「階段抜き」「ノンエスカレーター」「エレベスト」「効率の鬼」ならば同じ手が通用するはずです。

作成者の想定とは違うだろうという意味で「邪道」な感じはしますが、バグを突いた挙動でもなさそうだし、早解きしたい方は利用してみても良いでしょう。

[編集者: すずき]
[更新: 2020年 6月 28日 01:21]

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
   2020年 7月 7日 -
      2020年 6月 28日  
link もっと後

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www2.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 7/5 21:07

カレンダー

<2020>
<<<07>>>
---1234
567891011
12131415161718
19202122232425
262728293031-

最近のコメント 5件

  • link 20年06月29日
    すずき 「うちのマシンは基本速度が取得できてないん...」
    (更新:07/01 11:18)
  • link 20年06月29日
    hdk 「Athlon 5350 (2.05GHz...」
    (更新:06/30 23:55)
  • link 20年05月02日
    すずき 「ちょっと調べたところ、コアが焼けると騒ぎ...」
    (更新:05/08 15:43)
  • link 20年05月02日
    すずき 「結構、怖い制御に見えますね&hellip...」
    (更新:05/08 15:23)
  • link 20年05月02日
    hdk 「デスクトップ用のNVIDIA Quadr...」
    (更新:05/07 20:30)

最近の記事 3件

link もっとみる
  • link 20年07月05日
    すずき 「[ELF バイナリで SEGV その 2 - 64 バイト] 昨日...」
    (更新:07/05 21:07)
  • link 20年07月04日
    すずき 「[ELF バイナリで SEGV その 1 - 92 バイト] 昨日...」
    (更新:07/05 21:06)
  • link 20年07月03日
    すずき 「[C 言語で SEGV] SEGV を出すのが Twitter で...」
    (更新:07/05 18:58)

こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報