행렬곱

공부/자료구조 2021. 5. 9. 00:44
반응형
//Fn.c

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"Fn.h"


void printMatrix(int **Matrix, int m, int n){
	int m1, n1;
	for(m1=0;m1<m;m1++){
		for(n1=0;n1<n;n1++){
			if(n1 == n-1){
				printf("%d\n", Matrix[m1][n1]);
			}
			else
				printf("%d ", Matrix[m1][n1]);
		}
	}
}

//(m x n) matrix
void insertRand(int **Matrix, int m, int n){
	srand(time(NULL));
	int m1, n1;
	for(m1=0;m1<m;m1++){
		for(n1=0;n1<n;n1++){
			Matrix[m1][n1] = rand()%10000;
		}
	}
}

int** createMatrix(int m, int n){
	int **matrix;
	matrix = (int**)malloc(sizeof(int*)*m);
	for(int m1=0;m1<m;m1++){
		matrix[m1] = (int*)malloc(sizeof(int)*n);
	}
	
	return matrix;
}

void freeMatrix(int **matrix, int m, int n){
	int m1, n1;
	//arr[0][] ~~~~~~~~ a[m1][]
	for(m1=0;m1<m;m1++){
		free(matrix[m1]);
	}
	free(matrix);

}
//Fn.h

#include<stdio.h>

int** MultiplyMatrix(int **matrix1, int **matrix2, int m, int n, int q);
void printMatrix(int **Matrix, int m, int n);
void insertRand(int **Matrix, int m, int n);
int** createMatrix(int m, int n);
void freeMatrix(int **matrix, int m, int n);
void freeArr(int *arr);
//MatrixMultiplyTest.c

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"Fn.h"

void main(){
	//(m x n), (n x q)
	int m, n, q;
	int **Matrix1, **Matrix2, **result;
	clock_t start, end;
	float t;
	//seed
	srand(time(NULL));

	int i, j;
	//(100x100) ~ (599x599)
	for(j=100;j<600;j+=100){
		m = rand()%10 + j;
		n = rand()%10 + j;
		q = rand()%10 + j;
		printf("Matrix1(%dx%d) * Matrix2(%dx%d) \n",m,n,n,q); 
		//5times
		for(i=0;i<5;i++){
			//random m, n, q
			//create Matrix
			Matrix1 = createMatrix(m,n);
			Matrix2 = createMatrix(n,q);
			insertRand(Matrix1, m, n);
			insertRand(Matrix2, n, q);
		
			/*
			//show Matrix
			printf("=Matrix1=\n");
			printMatrix(Matrix1, m, n);
			printf("=Matrix2=\n");
			printMatrix(Matrix2, n, q);
				*/
	
			//start multiply
			start = clock();
			result = MultiplyMatrix(Matrix1, Matrix2, m, n, q);
			end = clock();
			t = (end - start)/CLOCKS_PER_SEC;
	
			/*
			//show MultiplyMatrix
			printf("=result=\n");
			printMatrix(result, m, q);
			*/
	
			//Time
			printf("Time : %.3f sec", t);
		
			freeMatrix(Matrix1, m, n);
			freeMatrix(Matrix2, n, q);
			freeMatrix(result, m, q);
		}
	}
}
//MultiplyMatrix.c

#include<stdio.h>
#include"Fn.h"
//(m x n) (n x q) => (m x q)
int** MultiplyMatrix(int **matrix1, int **matrix2, int m, int n, int q){
	int **result;
	int m1, n1, q1;
	int res;

	for(m1=0; m1<m; m1++){
		for(q1=0;q1<q;q1++){
			res = 0;
			for(n1=0;n1<n;n1++){
				res = res + matrix1[m1][n1]*matrix2[n1][q1];
			}
			result[m1][q1] = res;
		}
	}
	return result;
}

728x90
반응형
블로그 이미지

아상관없어

,
반응형

 

 

728x90
반응형

'공부 > 자료구조' 카테고리의 다른 글

연산자 우선순위를 반영하는 산술식의 이진트리 설계와 구현  (0) 2021.05.09
탐색트리, 정렬 알고리즘과 계산시간 비교  (0) 2021.05.09
행렬곱  (0) 2021.05.09
Huffman 트리  (0) 2021.05.09
정렬하기  (0) 2020.07.17
블로그 이미지

아상관없어

,
반응형

문자열 압축 알고리즘의 설계와 구현

(1) 100 글자 이상이 포함되는 글을 입력받아 Huffman tree를 생성

(2) 입력 받은 글의 Huffman 코드를 출력

(3) 출력된 코드를 입력받아 문자열을 출력

 

728x90
반응형

'공부 > 자료구조' 카테고리의 다른 글

연산자 우선순위를 반영하는 산술식의 이진트리 설계와 구현  (0) 2021.05.09
탐색트리, 정렬 알고리즘과 계산시간 비교  (0) 2021.05.09
행렬곱  (0) 2021.05.09
다항식 연산  (0) 2021.05.09
정렬하기  (0) 2020.07.17
블로그 이미지

아상관없어

,
반응형

 

flex

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';

export const Header = () => {
    return (
        <View style = {[styles.container, styles.header]}>
            <Text style={styles.text}>Header</Text>
        </View>
    );
};

export const Contents = () => {
    return (
        <View style={[styles.container, styles.contents]}>
            <Text style={styles.text}>Contents</Text>
        </View>
    );
};

export const Footer = () => {
    return (
        <View style ={[styles.container, styles.footer]}>
            <Text style={styles.text}>Footer</Text>
        </View>
    );
};




const styles = StyleSheet.create({
    container: {
        width: '100%',
        alignItems: 'center',
        justifyContent: 'center',
        height: 80,
    }, => contents와 text의 height는 80으로 고정

    header: {
        backgroundColor: '#f1c40f',
        height: 640,
    }, => header의 height는 640
    contents: {
        backgroundColor: '#3498db',
    },
    text: {
        fontSize: 26,
    },
});

=> 아이폰 11에서는 잘리지 않고 다 보이지만 에뮬레이터에선 잘려보인다.

 

flex를 이용하면 width, height와 달리 비율로 크기가 결정된다.

-flex의 값이 0일때는 설정된 width와 heigth값에 따라 크기가 결정

-양수일 경우 felx값에 비례하여 크기가 조정

ex)

(위의 코드에서 footer를 추가하는 것을 깜빡하였다.)

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';

export const Header = () => {
    return (
        <View style = {[styles.container, styles.header]}>
            <Text style={styles.text}>Header</Text>
        </View>
    );
};

export const Contents = () => {
    return (
        <View style={[styles.container, styles.contents]}>
            <Text style={styles.text}>Contents</Text>
        </View>
    );
};

export const Footer = () => {
    return (
        <View style ={[styles.container, styles.footer]}>
            <Text style={styles.text}>Footer</Text>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        width: '100%',
        alignItems: 'center',
        justifyContent: 'center',
        height: 80,
    },

    header: {
        flex: 1,
        backgroundColor: '#f1c40f',
        height: 640,
    },
    contents: {
        flex: 2,
        backgroundColor: '#3498db',
    },
    => 추가
    footer: {
        flex: 1,
        backgroundColor: '#1abc9c',
    },

    text: {
        flex: 3,
        fontSize: 26,
    },
});

1:2:1 비율로 나누어 채워지게 된다.

 

 

정렬

컴포넌트가 쌓이는 방향

- flexDirection사용

 

 

- justiftContent

 

flex-start : 시작점에서부터 정렬 (기본값)

flex-end : 끝에서부터 정렬

center : 중앙 정렬

space-between : 컴포넌트 사이의 공간을 동일하게 만들어서 정렬

space-around : 컴포넌트 각가의 주변 공간을 동일하게 만들어서 정렬

space-evenly : 컴포넌트 사이와 양 끝에 동일한 공간을 만들어서 정렬

 

- alignItems

 

flex-start : 시작점에서부터 정렬 (기본값)

flex-end : 끝에서부터 정렬

center : 중앙정렬

strecth : alignItems의 방향으로 컴포넌트 확장

baseline :  컴포넌트 내부의 텍스트 베이스라인을 기준으로 정렬

728x90
반응형

'공부 > 리액트 네이티브' 카테고리의 다른 글

스타일링  (0) 2021.05.08
리액트 네이티브 - 이벤트  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - button 컴포넌트  (0) 2021.05.06
블로그 이미지

아상관없어

,
반응형

JSX는 backgroundColor와 같이 카멜 표기법으로 작성해야한다.

 

expo init react-native-style

./src/App.js 생성

 

 

인라인 스타일링

컴포넌트에 직접 스타일을 입력하는 방식

객체 형태로 전달

import React from 'react';
import { View, Text } from 'react-native';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >
            <Text
                style={{
                    padding: 10,
                    fontSize: 26,
                    fontWeight: '600',
                    color: 'black',
                }}
            >
                Inline Styling - Text 
            </Text>
            
            <Text
                style ={{
                    padding: 10,
                    fontSize: 26,
                    fontWeight: '400',
                    color: 'red',
                }}
            >
                Inline Styling - Error               
            </Text>
        </View>
    );
};

export default App;

 

 

명확하게 어떤 스타일인지 보이지만,

비슷한 역할을 하는 컴포넌트에 동일한 코드가 반복되고,

어떤 이유로 해당 스타일이 적용되었는지 가늠하기 힘듬

 

 클래스 스타일링

컴포넌트의 태그에 직접 입력 X

스타일 시트에 정의된 스타일을 사용

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';

const App = () => {
    return (
        <View style = {styles.container}>
            <Text style = {styles.text}> Text </Text>
            <Text style = {styles.error}> Error </Text>
        </View>
    );
};


const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
=> padding, fontsize, fontweight, color를 지정한 이유를 보여줌
(예를 들어 색을 바꿀 때 text객체의 color만 바꾸어주면 되어 편함)
    text: {
        padding: 10,
        fontSize: 26,
        fontweight: '600',
        color: 'black',
    },
=> padding, fontsize, fontweight, color를 지정한 이유를 보여줌
    error: {
        padding: 10,
        fontSize: 26,
        fontWeight: '400',
        color: 'red',
    },

});


export default App;

 

여러개 스타일 적용

위의 text와 error는 중복된 스타일이 많음.

두 스타일 모두 Text 컴포넌트에 적용되는 스타일임

배열을 이용하여 여러 개의 스타일 적용

mport React from 'react';
import { StyleSheet, View, Text } from 'react-native';

const App = () => {
    return (
        <View style = {styles.container}>
            <Text style = {styles.text}> Text </Text>
            => 뒤에 오는 스타일이 앞에 있는 스타일을 덮음
            <Text style = {[styles.text,styles.error]}> Error </Text>
        </View>
    );
};


const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },

    text: {
        padding: 10,
        fontSize: 26,
        fontweight: '600',
        color: 'black',
    },

    error: {
        fontWeight: '400',
        color: 'red',
    },

});


export default App;

 

 

 

상황에 따라 인라인, 클래스 스타일 방식 혼용

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';

const App = () => {
    return (
        <View style = {styles.container}>
            <Text style = {[styles.tex, { color: 'green'}]}> Text </Text> <= 배열사용, 혼용
            <Text style = {[styles.text,styles.error]}> Error </Text>
        </View>
    );
};


const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },

    text: {
        padding: 10,
        fontSize: 26,
        fontWeight: '600',
        color: 'black',
    },

    error: {
        fontWeight: '400',
        color: 'red',
    },

});


export default App;

 

 

 

 

 

 

외부 스타일 사용

만든 스타일을 다양한 곳에서 사용가능

외부 파일에 스타일을 정의하고 여러개의 파일에서 스타일을 공통으로 사용

./src/styles.js 생성

import {StyleSheet} from 'react-native';

export const viewStyles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
});

export const textStyles = StyleSheet.create({
    text: {
        padding: 10,
        fontSize: 26,
        fontWeight: '600',
        color: 'black',
    },

    error: {
        fontWeight: '400',
        color: 'red',
    },
});

//App.js


import React from 'react';
import { View, Text } from 'react-native';
import { viewStyles, textStyles } from './styles'; => ./styles에서 viewStyles, textStyles 가져옴


const App = () => {
    return (
        <View style = {viewStyles.container}>
            <Text style = {[textStyles.text, { color: 'green'}]}> Text </Text>
            <Text style = {[textStyles.text,textStyles.error]}> Error </Text>
        </View>
    );
};




export default App;

 

728x90
반응형

'공부 > 리액트 네이티브' 카테고리의 다른 글

스타일 속성  (0) 2021.05.09
리액트 네이티브 - 이벤트  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - button 컴포넌트  (0) 2021.05.06
블로그 이미지

아상관없어

,
반응형

press 이벤트

onClick 과 비슷한 이벤트

TouchableOpacity 컴포넌트에서 설정할 수 있는 Press 이벤트의 종류는 4가지임

onPressIn : 터치가 시작될때 항상 호출

onPressOut : 터치가 해제될 때 항상 호출

onPress : 터치가 해제될때 onPressOut 이후 호출

onLongPress : 터치가 일정 시간 이상 지속되면 호출

import React from 'react';
import { TouchableOpacity, Text } from 'react-native'

const EventButton = () => {
    const _onPressIn = () => console.log('Press In!!\n');
    const _onPressOut = () => console.log('Press Out!!\n');
    const _onPress = () => console.log('Press !!\n');
    const _onLongPress = () => console.log('Long Press !!\n');


    return (
        <TouchableOpacity
            sytle={{
                backgroundCloer: '#f1c40f',
                padding: 16,
                margin: 10,
                borderRadius: 8,
            }}

            onPressIn={_onPressIn}
            onLongPress={_onLongPress}
            onPressOut={_onPressOut}
            onPress={_onPress}
        >
            <Text style={{color: 'white', fontSize: 24}}>Press</Text>
        </TouchableOpacity>
    );
};

export default EventButton;
import React from 'react';
import {View} from 'react-native';
import EventButton from './components/EventButton';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >
            <EventButton /> 

        </View>
    );
};


export default App;

 

 

change 이벤트

change는 값을 입력하는 TextInput 컴포넌트에서 많이 사용된다.

import React, { useState } from 'react';
import { View, Text, TextInput } from 'react-native';

const EventInput = () => {
    const [text, setText] = useState('');
    const _onChange = event => setText(event.nativeEvent.text);
    return(
        <View>
            <Text style = {{ margin: 10, fontSize: 30}}>text: {text}</Text>
            <TextInput
                style={{ borderWidth: 1, padding: 10, fontSize: 20}}
                onChange={_onChange}
            />
        </View>
    );
};

export default EventInput;

TextInput 

import React from 'react';
import {View} from 'react-native';
import EventButton from './components/EventButton';
import EventInput from './components/EventInput';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >

            <EventInput />

        </View>
    );
};


export default App;

 

 

 

728x90
반응형

'공부 > 리액트 네이티브' 카테고리의 다른 글

스타일 속성  (0) 2021.05.09
스타일링  (0) 2021.05.08
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - button 컴포넌트  (0) 2021.05.06
블로그 이미지

아상관없어

,
반응형

props : properties의 줄임마로, 부모 컴포넌트로부터 전달된 속성값 또는 상속받은 속성값을 말함.

부모 컴포넌트에서 자식 컴포넌트의 props를 설정하면 자식 컴포넌트에서는 해당 props를 사용할 수 있고, 수정은 부모 컴포넌트에서만 가능하다.

 

props 전달, 사용

App.js

import React from 'react';
import {Text, View} from 'react-native';
import MyButton from './components/MyButton';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        
            <Text
                style={{
                    fontSize: 30,
                    marginBottom: 10,
                }}
            >
                Props
            </Text>
            //App컴포넌트에서 MyButton 컴포넌트를 호출할 때 title 속성에 Button이라는 문자열을 전달
            <MyButton title='Button' /> 
        </View>
    );
};

export default App;

MyButton.js

//리액트를 불러와서 사용할 수 있게 해줌(JSX는 React.createElement를 호출 하는 코드로 컴파일 되므로 반드시 작성)
import React from 'react';
//리액트 네이티브에서 제공되는 Pressable, Text 컴포넌트 추가
import{TouchableOpacity, Text} from 'react-native';

//Pressable 컴포넌틀르 사용해서 클릭에 대해 상호작용 할 수 있도록함.
//버튼에 내용표시하기위해 text컴포넌트 사용
//MyButton에서 부모로부터 전달된 props를 함수의 파라미터로 받음
const MyButton = props => {
	/*
    	console.log(porps);
        결과:
        Object { "title": "Button", }
    */
    return (
        <TouchableOpacity
            style={{
                backgroundColor: '#3498db',
                padding: 16,
                margin: 10,
                borderRaduis: 8,
            }}
            onPress={() => alert('click')}
        >
        	//props.title로 title값 읽어서 출력
            <Text style={{color: 'white', fotSize: 24}}>{props.title}</Text>
        </TouchableOpacity>
    );
};

export default MyButton;

MyButton의 이름이 props.title로 읽어들여 Button으로 되었다.

 

컴포넌트의 태그 사이에 값을 입력하여 전달할 수도 있다.

App.js
===============================================================
import React from 'react';
import {Text, View} from 'react-native';
import MyButton from './components/MyButton';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        
            <Text style={{ fontSize: 30, marginBottom: 10, }}>
                Props
            </Text>
            <MyButton title="Button" /> 
            <MyButton title="Button">Children Props</MyButton> =>태그사이에 전달된 값은 자식 컴포넌트의 props의 children으로 전달됨
        </View>
    );
};

export default App;



MyButton.js
===============================================================
//리액트를 불러와서 사용할 수 있게 해줌(JSX는 React.createElement를 호출 하는 코드로 컴파일 되므로 반드시 작성)
import React from 'react';
//리액트 네이티브에서 제공되는 Pressable, Text 컴포넌트 추가
import{TouchableOpacity, Text} from 'react-native';

//Pressable 컴포넌틀르 사용해서 클릭에 대해 상호작용 할 수 있도록함.
//버튼에 내용표시하기위해 text컴포넌트 사용
const MyButton = props => {
    return (
        <TouchableOpacity
            style={{
                backgroundColor: '#3498db',
                padding: 16,
                margin: 10,
                borderRaduis: 8,
            }}
            onPress={() => alert('click')}
        >
            <Text style={{color: 'white', fotSize: 24}}>
                {props.children || props.title}
                </Text>
        </TouchableOpacity>
    );
};

export default MyButton;



props에 children이 있다면 title보다 우선시 되도록 작성

 

 

defaultProps

App.js에

버튼을 추가하고 아무런 값을 넘겨주지 않으면

<MyButton />

아무 표시가 되지 않는다. 

이러한 일을 방지하기 위해(반드시 전달되어야하는 값이 전달되게 설정)

MyButton.js에

MyButton.defaultProps = {

    title: 'Button',

};

를 추가하면 

MyButton 컴포넌트의 defaultProps 덕분에 기본으로 설정한 Button이 전달되었다.

 

 

 

 

propTypes

컴포넌트에 props를 전달할 때 잘못된 타입을 전달하거나, 필수로 전달해야하는 값을 전달하지 않았을 때

잘못된 props가 전달되었다고 경고하는 방법

컴포넌트에서 전달받아야하는 props의 타입과 필수 여부를 지정할 수 있음

 "npm install prop-types"

MyButton.js

MyButton.propTypes = {
	title: PropTypes.number,
};

title에 전달되어야 하는 값이 number라고 지정함

따라서 이전과 같이 String을 전달할 시 경고 메시지가 나타난다.

 

필수전달여부 => 선언된 타입 뒤에 isRequired만 붙여주면 된다.

MyButton.js

MyButton.propTypes = {
	title: PropTypes.string.isRequired,
    	name: PropTypes.string.isREquired,
};

App.js 에서 name을 전달해주지 않았으므로 에러가 발생하게 된다.

 

함수, 객체, 배열 등의 다양한 타입도 지정할 수 있다.

ex) onPress 필수로 지정

MyButton.js

MyButton.propTypes = {
	title: PropTypes.string.isRequired,
    	onPress: PropTypes.func.isRequired,
};
App.js

...
	    <MyButton title="Button" onPress={()=> alert("Click)}/> 
            <MyButton title="Button onPress={()=> alert("Click)}">
            	Children Props
            </MyButton> 
            <MyButton onPress={()=> alert("Click)}/>
....

 

 

 

 

useState

-State

컴포넌트 내부에서 생성되고 값을 변경할 수 있다.

이를 이용하여 컴포넌트 상태를 관리한다.

state : 컴포넌트에서 변화할 수 있는 값 ( 상태가 변하면 컴포넌트는 리렌더링 된다.)

 

 

useState는 상태를 관리하는 변수, 그 변수를 변경할 수 있는 setter 함수를 배열로 반환한다.

const [state, setState] = useState(initialState);

상태변수 state는 useState 함수에서 반환한 setter함수를 이용하여 변경하여야한다.

호출시 파라미터로 상태의 초기값을 전달한다.

(초기값을 전달하지 않으면 undefined로 설정되어 에러가 발생)

 

./src/component/Counter.js

import React, {useState} from 'react';
import { View, Text } from 'react-native';
import MyButton from './MyButton';

const Counter = () => {
    const [count, setCount] = useState(0);
    return (
        <View style={{ alignItems: 'center'}}>
            <Text style={{fontSize: 30, margin: 10}}>{count}</Text>
            <MyButton title = '+1' onPress={() => setCount(count + 1)} />
            <MyButton title = "-1" onPress={() => setCount(count - 1)} />
        </View>
    )
}

 

import React from 'react';
import {View} from 'react-native';
import Counter from './components/Counter';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        
            <Text style={{ fontSize: 30, marginBottom: 10, }}>
                Props
            </Text>
            <MyButton title="Button" /> 
            <MyButton title="Button">Children Props</MyButton> 
            <MyButton />

            <counter /> <=counter 컴포넌트 추가

        </View>
    );
};


export default App;

 

 

728x90
반응형

'공부 > 리액트 네이티브' 카테고리의 다른 글

스타일링  (0) 2021.05.08
리액트 네이티브 - 이벤트  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - button 컴포넌트  (0) 2021.05.06
리액트 네이티브 - jsx  (0) 2021.05.06
블로그 이미지

아상관없어

,
반응형

props : properties의 줄임마로, 부모 컴포넌트로부터 전달된 속성값 또는 상속받은 속성값을 말함.

부모 컴포넌트에서 자식 컴포넌트의 props를 설정하면 자식 컴포넌트에서는 해당 props를 사용할 수 있고, 수정은 부모 컴포넌트에서만 가능하다.

 

props 전달, 사용

App.js

import React from 'react';
import {Text, View} from 'react-native';
import MyButton from './components/MyButton';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        
            <Text
                style={{
                    fontSize: 30,
                    marginBottom: 10,
                }}
            >
                Props
            </Text>
            //App컴포넌트에서 MyButton 컴포넌트를 호출할 때 title 속성에 Button이라는 문자열을 전달
            <MyButton title='Button' /> 
        </View>
    );
};

export default App;

MyButton.js

//리액트를 불러와서 사용할 수 있게 해줌(JSX는 React.createElement를 호출 하는 코드로 컴파일 되므로 반드시 작성)
import React from 'react';
//리액트 네이티브에서 제공되는 Pressable, Text 컴포넌트 추가
import{TouchableOpacity, Text} from 'react-native';

//Pressable 컴포넌틀르 사용해서 클릭에 대해 상호작용 할 수 있도록함.
//버튼에 내용표시하기위해 text컴포넌트 사용
//MyButton에서 부모로부터 전달된 props를 함수의 파라미터로 받음
const MyButton = props => {
	/*
    	console.log(porps);
        결과:
        Object { "title": "Button", }
    */
    return (
        <TouchableOpacity
            style={{
                backgroundColor: '#3498db',
                padding: 16,
                margin: 10,
                borderRaduis: 8,
            }}
            onPress={() => alert('click')}
        >
        	//props.title로 title값 읽어서 출력
            <Text style={{color: 'white', fotSize: 24}}>{props.title}</Text>
        </TouchableOpacity>
    );
};

export default MyButton;

MyButton의 이름이 props.title로 읽어들여 Button으로 되었다.

 

컴포넌트의 태그 사이에 값을 입력하여 전달할 수도 있다.

App.js
===============================================================
import React from 'react';
import {Text, View} from 'react-native';
import MyButton from './components/MyButton';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        
            <Text style={{ fontSize: 30, marginBottom: 10, }}>
                Props
            </Text>
            <MyButton title="Button" /> 
            <MyButton title="Button">Children Props</MyButton> =>태그사이에 전달된 값은 자식 컴포넌트의 props의 children으로 전달됨
        </View>
    );
};

export default App;



MyButton.js
===============================================================
//리액트를 불러와서 사용할 수 있게 해줌(JSX는 React.createElement를 호출 하는 코드로 컴파일 되므로 반드시 작성)
import React from 'react';
//리액트 네이티브에서 제공되는 Pressable, Text 컴포넌트 추가
import{TouchableOpacity, Text} from 'react-native';

//Pressable 컴포넌틀르 사용해서 클릭에 대해 상호작용 할 수 있도록함.
//버튼에 내용표시하기위해 text컴포넌트 사용
const MyButton = props => {
    return (
        <TouchableOpacity
            style={{
                backgroundColor: '#3498db',
                padding: 16,
                margin: 10,
                borderRaduis: 8,
            }}
            onPress={() => alert('click')}
        >
            <Text style={{color: 'white', fotSize: 24}}>
                {props.children || props.title}
                </Text>
        </TouchableOpacity>
    );
};

export default MyButton;



props에 children이 있다면 title보다 우선시 되도록 작성

 

 

defaultProps

App.js에

버튼을 추가하고 아무런 값을 넘겨주지 않으면

<MyButton />

아무 표시가 되지 않는다. 

이러한 일을 방지하기 위해(반드시 전달되어야하는 값이 전달되게 설정)

MyButton.js에

MyButton.defaultProps = {

    title: 'Button',

};

를 추가하면 

MyButton 컴포넌트의 defaultProps 덕분에 기본으로 설정한 Button이 전달되었다.

 

 

 

 

propTypes

컴포넌트에 props를 전달할 때 잘못된 타입을 전달하거나, 필수로 전달해야하는 값을 전달하지 않았을 때

잘못된 props가 전달되었다고 경고하는 방법

컴포넌트에서 전달받아야하는 props의 타입과 필수 여부를 지정할 수 있음

 "npm install prop-types"

MyButton.js

MyButton.propTypes = {
	title: PropTypes.number,
};

title에 전달되어야 하는 값이 number라고 지정함

따라서 이전과 같이 String을 전달할 시 경고 메시지가 나타난다.

 

필수전달여부 => 선언된 타입 뒤에 isRequired만 붙여주면 된다.

MyButton.js

MyButton.propTypes = {
	title: PropTypes.string.isRequired,
    	name: PropTypes.string.isREquired,
};

App.js 에서 name을 전달해주지 않았으므로 에러가 발생하게 된다.

 

함수, 객체, 배열 등의 다양한 타입도 지정할 수 있다.

ex) onPress 필수로 지정

MyButton.js

MyButton.propTypes = {
	title: PropTypes.string.isRequired,
    	onPress: PropTypes.func.isRequired,
};
App.js

...
	    <MyButton title="Button" onPress={()=> alert("Click)}/> 
            <MyButton title="Button onPress={()=> alert("Click)}">
            	Children Props
            </MyButton> 
            <MyButton onPress={()=> alert("Click)}/>
....

 

 

 

 

useState

-State

컴포넌트 내부에서 생성되고 값을 변경할 수 있다.

이를 이용하여 컴포넌트 상태를 관리한다.

state : 컴포넌트에서 변화할 수 있는 값 ( 상태가 변하면 컴포넌트는 리렌더링 된다.)

 

 

useState는 상태를 관리하는 변수, 그 변수를 변경할 수 있는 setter 함수를 배열로 반환한다.

const [state, setState] = useState(initialState);

상태변수 state는 useState 함수에서 반환한 setter함수를 이용하여 변경하여야한다.

호출시 파라미터로 상태의 초기값을 전달한다.

(초기값을 전달하지 않으면 undefined로 설정되어 에러가 발생)

 

./src/component/Counter.js

import React, {useState} from 'react';
import { View, Text } from 'react-native';
import MyButton from './MyButton';

const Counter = () => {
    const [count, setCount] = useState(0);
    return (
        <View style={{ alignItems: 'center'}}>
            <Text style={{fontSize: 30, margin: 10}}>{count}</Text>
            <MyButton title = '+1' onPress={() => setCount(count + 1)} />
            <MyButton title = "-1" onPress={() => setCount(count - 1)} />
        </View>
    )
}

 

import React from 'react';
import {View} from 'react-native';
import Counter from './components/Counter';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        

            <counter /> <=counter 컴포넌트 추가

        </View>
    );
};


export default App;

 

728x90
반응형

'공부 > 리액트 네이티브' 카테고리의 다른 글

리액트 네이티브 - 이벤트  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - button 컴포넌트  (0) 2021.05.06
리액트 네이티브 - jsx  (0) 2021.05.06
리액트 네이티브  (0) 2021.05.02
블로그 이미지

아상관없어

,
반응형

컴포넌트 : 재사용 가능한 조립블록, 화면에 나타나는 UI 요소

App.js도 App이라는 컴포넌트이다.

부모로부터 받은 속성이나 자신의 상태에 따라 표현이 달라지고 다양한 기능 수행

 

 

내장 컴포넌트 => App.js의 View나 Text 컴포넌트가 대표적인 내장 컴포넌트

https://reactnative.dev/docs/compnents-and-apis

 

 

Button 컴포넌트

https://reactnative.dev/docs/button

 

./src/App.js

import React from 'react';
import {Text, View, Button} from 'react-native';

const App = () => {
    return (
        <View
        //style 정의
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >
            //출력될 text
            <Text style={{ fontSize: 30, marginBottom: 10 }}>Button Component</Text>
            //버튼에 출력될 text는 title 속성이용, 클릭시 click이 뜨도록 onPress 속성에 함수 지정
            <Button title="Button" onPress={() => alert('Click !!!')} />
        </View>
    );
};

export default App;

 

 

./App.js

import { StatusBar } from 'expo-status-bar';

import App from './src/App'; //./src/App 컴포넌트 사용

export default App;

(button 컴포넌트의 color 속성은 ios에서 텍스트 색을 나타내는 값, 안드로이드에서는 버튼의 바탕색을 나타내는 값)

 

 

 

 

커스텀 컴포넌트

TouchableOpacity 컴포넌트와 Text컴포넌트를 이용해서 MyButton 컴포넌트 생성

(리액트 네이티브 0.63버전에서 Pressable 컴포넌트가 TouchableOpacity컴포넌트를 대체함)

 

 

- ./src에 컴포넌트를 관리할 components 폴더 생성

- MyButton.js 생성

//리액트를 불러와서 사용할 수 있게 해줌(JSX는 React.createElement를 호출 하는 코드로 컴파일 되므로 반드시 작성)
import React from 'react';
//리액트 네이티브에서 제공되는 Pressable, Text 컴포넌트 추가
import{TouchableOpacity, Text} from 'react-native';

//Pressable 컴포넌틀르 사용해서 클릭에 대해 상호작용 할 수 있도록함.
//버튼에 내용표시하기위해 text컴포넌트 사용
const MyButton = () => {
    return (
        <TouchableOpacity>
            <Text style={{fontSize: 24}}>My Button</Text>
        </TouchableOpacity>
    );
};

export default MyButton;

- ./App.js 수정

import React from 'react';
import {Text, View} from 'react-native';
import MyButton from './components/MyButton';

const App = () => {
    return (
        <View
            style={{
                flex: 1,
                backgroundColor: '#fff',
                alignItems: 'center',
                justifyContent: 'center',
            }}
        >        
            <Text
                style={{
                    fontSize: 30,
                    marginBottom: 10,
                }}
            >
                My Button Component
            </Text>
            <MyButton />
        </View>
    );
};

export default App;

 

MyButton이 생성된다.

 

TouchableOpacity컴포넌트는 onPress 속성을 제공하는 TouchableWithoutFeedback 컴포넌트를 상속 받았기 때문에 onPress 속성을 지정하고 사용할 수 있음

//리액트를 불러와서 사용할 수 있게 해줌(JSX는 React.createElement를 호출 하는 코드로 컴파일 되므로 반드시 작성)
import React from 'react';
//리액트 네이티브에서 제공되는 Pressable, Text 컴포넌트 추가
import{TouchableOpacity, Text} from 'react-native';

//Pressable 컴포넌틀르 사용해서 클릭에 대해 상호작용 할 수 있도록함.
//버튼에 내용표시하기위해 text컴포넌트 사용
const MyButton = () => {
    return (
        <TouchableOpacity
            style={{
                backgroundColor: '#3498db',
                padding: 16,
                margin: 10,
                borderRaduis: 8,
            }}
            onPress={() => alert('click')}
        >
            <Text style={{color: 'white', fotSize: 24}}>My Button</Text>
        </TouchableOpacity>
    );
};

export default MyButton;

 

 

728x90
반응형

'공부 > 리액트 네이티브' 카테고리의 다른 글

리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - props  (0) 2021.05.06
리액트 네이티브 - jsx  (0) 2021.05.06
리액트 네이티브  (0) 2021.05.02
자바스크립트 - 정리  (0) 2021.04.30
블로그 이미지

아상관없어

,
반응형

컴포넌트 : 재사용할 수 있는 조립 블럭, 화면에 나타나는 UI요소라고 생각

와이어프레임 : 최종화면에 구성될 콘텐츠를 간단히 요약해서 보여주는 것

 

expo init react-native-component

 

App.js

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

javascript 이지만 html과 같은 코드들이 보인다. 이러한 코드를 jsx라 한다.

jsx는 객체 생성과 함수 호출을 위한 문법적 편의를 제공하기 위해 만들어진 확장기능이다.

export default function App() {
 return (
   <Text>Open up App.js to start working on your app!</Text>
   <StatusBar style="auto" />
 )
}



위와 같이 App.js를 변경하면 
JSX 식에는 부모 요소가 하나 있어야 합니다.ts(2657)
와 같은 에러가 발생한다.

 

JSX에서는 여러개의 요소를 반환하는 경우에도 반드시 하나의 부모로 나머지 요소를 감싸서 반환해야한다.

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
 return (
   <View style={styles.container}>
    <Text>Open up App.js to start working on your app!</Text>
    <StatusBar style="auto" />
   </View>
 )
}

view는 UI를 구성하는 가장 기본적인 요소이다.

 

view 컴포넌트말고 여러 개의 컴포넌트를 반환하고 싶은 경우 Fragment 컴포넌트를 사용한다.

import { StatusBar } from 'expo-status-bar';
import React, {Fragment} from 'react';
import {Text} from 'reat-native';

export default function App() {
 return (
   <Fragment>
    <Text>Open up App.js to start working on your app!</Text>
    <StatusBar style="auto" />
   </Fragment>
 )
}

/*
==============
export default function App() {
 return (
   <>
    <Text>Open up App.js to start working on your app!</Text>
    <StatusBar style="auto" />
   </>
 )
}
와 같이 사용하여도 됨
*/

import React, {Fragment} from 'react';

Fragment를 사용하기 위해 import를 이용하여 불러오고 Fragment  컴포넌트를 사용하도록 함

 

 

<name 변수에 이름 넣어서 출력>

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';

export default function App() {
 const name = 'Changmin'
 return (
   <View style = {styles.container}>
     <Text style={styles.text}>My name is {name}</Text>
   </View>
 )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text:{
    fontSize: 30,
  },
});

 

 

JSX내부에서 if문을 사용할 수 있지만 즉시실행함수 형태로 작성해야한다.

(즉시 실행 함수)

----------------------------------------------------------------------------

함수를 정의함과 동시에 바로 실행하는 함수

(function (name) { console.log('즉시실행함수' + name); })('foo'); 또는

- function 삭제 가능

( (name) => { console.log('즉시실행함수' + name); })();

----------------------------------------------------------------------------

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';

export default function App() {
 const name = 'abcd'
 return (
   <View style = {styles.container}>
     <Text style={styles.text}>
      {(() => {
        if (name === 'Changmin') return 'My name is Changmin';
        else if (name === 'Noname') return 'My name is Noname';
        else return 'My name is react-native';
      })()}
     </Text>
   </View>
 )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text:{
    fontSize: 30,
  },
});

 

jsx에서는 false는 랜더링 되지 않는다.

따라서

name === 'name' && (실행할 코드)

name !== 'name' && (실행할 코드) 

처럼 특정 조건일때 컴포넌트의 랜더링 여부를 결정할 수 있다.

 

 

Inline 스타일링

jsx에서는 style에 문자열로 입력하는 것이 아니라 객체형태로 입력해야한다.

-으로 연결된 이름은 하이픈을 제거하고 카멜표기법으로 작성해야한다. camelCode

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import {Text, View} from 'react-native';

export default function App() {
 return (
   <View
      style = {{
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'ceonter',
        justifyContent: 'center',
      }}
    >
      <Text>Open up App.js to start working on your app!</Text>
    </View>
 )
}

728x90
반응형
블로그 이미지

아상관없어

,
반응형

- trainset.csv 파일을 이용하여 classification 모델 생성

- 모델을 이용하여 testset.csv 파일의 자료에 대한 class 예측

 

trainset.csv

(A열이 class label이다.)

 

testset.csv

 

- 예측결과 포맷

=========================================================================

model development process[Feature Selection -> Algorithm Selection -> Hyper parameter tuning] 순이므로, 먼저 어떠한 Feature을 고를 것인지 결정하였습니다.

Feature Selection 방법으로 강의에서 배운 filter method, backward elimination, forward selection 세가지 방법으로 테스트를 하였습니다. Feature selection을 하기 위해 model을 선택하여야 했는데, 이는 강의에서 배운 model comparison을 통하여 선정하였습니다.

기존에 배운 분류 알고리즘인 DecisionTreeClassifier, KNeighborsClassifier, RandomForestClassifier, SVC 외에 검색을 통하여 몇 가지 알고리즘을 추가하였습니다. 자주 사용되는 Xgboost, xgboost의 느린 단점을 보완한 LightGBM을 추가하여 비교를 하였습니다. (pip install 명령어를 사용하여 설치함)

5번 반복하여 비교한 결과 RandomForestxgboost, LightGBM이 모델 변동폭이 작고 정확도도 높은 것을 알 수 있어 이 3가지 모델을 사용하여 비교해보기로 하였습니다.

from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
from xgboost import plot_importance

# Model comparison 
import matplotlib.pyplot as plt
from sklearn import model_selection

# from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
import pandas as pd
import numpy as np
import pprint as pp

#1. 데이터 셋 준비
data = pd.read_csv('C:\dataset/trainset.csv')

#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]

# train, test 나눔
train_X, test_X, train_y, test_y = train_test_split(data_x, data_y, test_size=0.3,random_state=1234) 



# prepare configuration for cross validation test harness
seed = 7

# prepare models
models = []
models.append(('KNN', KNeighborsClassifier()))
models.append(('DT', DecisionTreeClassifier()))
models.append(('RF', RandomForestClassifier()))
models.append(('SVM', SVC()))
models.append(('xgboost', XGBClassifier()))
models.append(('LGBM', LGBMClassifier()))
results = []
names = []
scoring = 'accuracy'

for name, model in models:
    kfold = model_selection.KFold(n_splits=10, random_state=seed, shuffle=True)
    cv_results = model_selection.cross_val_score(model, data_x, data_y, cv=kfold, scoring=scoring)
    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)
    
print(results)

# average accuracy of classifiers
for i in range(0,len(results)):
    print(names[i] + "\t" + str(round(np.mean(results[i]),4)))
    
# boxplot algorithm comparison
fig = plt.figure()
fig.suptitle('Algorithm Comparison')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.show()

그리고 filter method, backward elimination, forward selection을 통하여 feature을 선정하였습니다.

(먼저 데이터 셋의 column name이 없어 0부터 숫자를 순서대로 할당하여 보기 편하게 하였습니다. Backward n_features_to_select=4, Cv=5)

 

[모델 선택하기 위해 비교]

 

LighGBM의 경우

[filter method]

“0.9159”

[backward elimination]

“0.7869”

 

[forward selection]

“0.871”

 

 

 

 

RandomForest의 경우

[filter method]

“0.909”

[backward elimination]

“0.849”

 

[Forward selection]

“0.871”

 

 

 

 

 

Xgboost의 경우

[filter method]

“0.907”

 

[backward elimination]

“0.850”

 

[Forward selection]

“0.872”

 

각기 다른 모델을 사용해도 feature의 중요도는 바뀌질 않으니 빠른 lightGBM 모델로 backward, forward selection에서 각 인자 n_features_to_select, k_features의 수를 filter method 에서 얻은 데이터를 바탕으로 수정하여 한번 더 테스트 하였습니다.

Filter method의 결과를 보면 선택하는 feature의 수가 많아질수록 정확도가 높아지므로 개수를 크게 변화가 없어지는 21개부터 30개까지 테스트를 해보았습니다.

하지만 forward selction을 할 경우 시간이 오래 걸리고 컴퓨터도 간헐적으로 멈추어 backward elimination으로 테스트하였습니다.

 

 

# Feature selection Example
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import LabelEncoder
#from xgboost import XGBClassifier
from lightgbm import LGBMClassifier

#1. 데이터 셋 준비
name = []
for i in range(0,32):
    name.append(i)  
data = pd.read_csv('C:\dataset/trainset.csv', names = name)
print(data.head())
#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]
# whole features
model = LGBMClassifier()
scores = cross_val_score(model, data_x, data_y, cv=5)
print("Acc: "+str(scores.mean()))
print('######################################################################')
print('# feature selection by filter method')
print('######################################################################')
######################################################################
# feature selection by filter method
######################################################################
# feature evaluation method : chi-square
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
test = SelectKBest(score_func=chi2, k=data_x.shape[1])
fit = test.fit(data_x, data_y)

# summarize evaluation scores
print(np.round(fit.scores_, 3)) #소수점 3자리까지 반올림
f_order = np.argsort(-fit.scores_) # sort index by decreasing order
sorted_columns = data.columns[f_order]
f_order
data_x.shape[1]
# test classification accuracy by selected features
model = XGBClassifier()

for i in range(0, data_x.shape[1]):
    fs = sorted_columns[0:i]
    data_x_selected = data_x[fs]
    scores = cross_val_score(model, data_x_selected, data_y, cv=5)
    print(fs.tolist())
    print(np.round(scores.mean(), 4))

'''
for i in range(20, 31):
    
    print('index = ', i)
'''
    ######################################################################
    # Backward elimination (Recursive Feature Elimination)
    ######################################################################
    from sklearn.feature_selection import RFE
    
model = LGBMClassifier()
    rfe = RFE(model, n_features_to_select=i)
    fit = rfe.fit(data_x, data_y)
    print("Num Features: %d" % fit.n_features_)
    fs = data_x.columns[fit.support_].tolist() # selected features
    print("Selected Features: %s" % fs)
    scores = cross_val_score(model, data_x[fs], data_y, cv=5)
    print("Acc: "+str(scores.mean()))



    print('######################################################################')
    print('# Forward selection')
    print('######################################################################')
    ######################################################################
    # Forward selection
    ######################################################################
    # please install 'mlxtend' moudle
    from mlxtend.feature_selection import SequentialFeatureSelector as SFS
    model = LGBMClassifier()
    sfs1 = SFS(model, k_features=i, n_jobs=-1, scoring='accuracy', cv=5)
    sfs1 = sfs1.fit(data_x, data_y, custom_feature_names=data_x.columns)
    sfs1.subsets_ # selection process
    sfs1.k_feature_idx_ # selected feature index
    print(sfs1.k_feature_names_)# selected feature name
    
    

Backward elimination을 하였을 때

 

Feature25개 사용하면 정확도가 0.9165으로 가장 좋았지만, 나머지와 비교하였을 때 filter method도 그러하듯이 feature 개수에 따른 큰 차이를 보여주지 못하여 테스트 시 모든 feature들을 사용하기로 결정하였습니다.

 

이제 hyperparameter 튜닝을 하기 전 각 모델별로 테스트를 해보았다.

 

Feature을 선정하기 위한 과정에서 model도 함께 선정하였으므로 다음으로 hyperparameter tuning을 진행하였습니다. Hyper parameter를 찾기 위해 RandomizedSearchCV 방법을 사용하였습니다.

 

(다른 최적화 방법 BaysianOptimizaion을 찾았으나 정확한 사용법을 익히지 못하여 RandomizedSearchCV 방법을 사용하였습니다.

또한 autosklearn을 통하여 최적의 모델을 찾고 hyper parameter 최적값을 찾는 과정을 자동으로 해주려 하였으나, 다음의 글을 찾아Anaconda does not ship auto-sklearn, and there are no conda packages for auto-sklearn” 이 방법은 해보지 못하였습니다.

-Xgboost

max_depth(int, default: 3): 기본 학습자를 위한 최대 트리 깊이

learning_rate(float, default: 0.1) : Boosting 학습률

n_estimators(int, default: 100) : fit하기 위한 Boosted tree

silent(boolean, default: True : Boosting 실행하는 동안 메시지를 print할지 여부

objective(string or callable, default:’reg:linear’) : 학습할 Objective Function 사용

booster(string, default: ‘gbtree’): Booster 사용할 모드 gbtree, gblinear, dart

nthread(int, default: ‘None’): xgboost 실행하는데 사용할 병렬 스레드

- xgboost.XGBClassifier(nthread=20)

n_jobs(int, default: 1): xgboost 실행하는데 사용할 병렬 스레드

gamma(float, default: 0): 트리의 leaf 노드에 추가 파티션(partition) 만들때 최소 손실 감소(Minimum loss reduction) 필요하다.

min_child_weight(int, default: 1): Child 노드에 필요한 instance weight(hessian) 최소 합계

max_delta_step(int): Tree 가중치(Weight) 추정을 허용하는 최대 Delta 단계

subsample(float): 학습(Training) Instance Subsample 비율

colsample_bytree(float): Tree 구성할 column Subsample 비율

colsample_bylevel(float): Tree Level에서 분할(split) 대한 column Subsample

 

처음햇을 때

 

max_depth를 늘리니 향상되는 것을 알 수 있었다.

따라서 max_depth를 더 늘려 테스트해보려 하였지만, 실수로 n_estiators np.linspace(start = 200, stop = 10000, num = 21)와 같이 늘려서 테스트 하였다.

시간은 2시간 가량 걸렸지만, n_estimators의 값은 크게 영향이 없다는 것을 알았다.

Max_depth값이 늘어났을 때 성능이 향상되는 것을 알 수 있었다.

 

np.linspace(4000, 10000, num = 11)로 바꾸어 하였을 때,

비슷한 향상 폭을 보여주었다.

 

 

-RandomForest

예제코드와 같이 실행을 하면

1.21%의 향상을 얻을 수 있었습니다.

 

위와 같이 각 모델에 대해 HyperParameter를 진행하려하였으나,

tuningparameter들의 수가 많고 tuning을 하는 과정도 상당한 시간이 걸려,

시간 비용을 줄이고자 분산이 적고 예측력이 세가지 모델 중 가장 좋은 LightGBM을 선택하여 hyper parameter tuning을 하고 테스트를 진행하였습니다.

=========================================================================

 

초반에는 여러 데이터들의 범위를 바꾸어 가면서 테스트를 하였습니다.

2000 candidates를 하였지만 시간대비 좋지 않은 결과를 얻었다.

Xboost에서 max_depth가 커지면서 좋아진 것을 보고 LightGBM에서도 값을 크게 잡아서 테스트를 하였다.

Candidates100이지만 성능이 더 좋아진 것으로 보아 candidate를 크게 잡을 필요가 없다고 생각하였습니다.

 

그리고 num_leaves를 바꾸어 테스트하였으나 결과에 변화가 없는 것으로 보아 num_leaves는 큰 영향을 끼치지 않는 것으로 확인했다.

min_data_in_leaf가 커지면 향상 폭이 줄어드는 것을 확인하였다.

 

따라서 max_depth가 크면 향상 폭이 가장 좋아지는 것으로 판단하였다.

parameter들을 범위를 넓혀 가면서 테스트를 하였다.

범위를 넓게 한 경우

 

그리고 default parameter를 사용할 때와 0.82%의 향상이 있었던 파라미터를 사용하여 테스트해보았습니다.

Default의 경우 0.93이 나왔고, 향상된 파라미터를 사용할 경우 0.90으로 줄어들었습니다. 과적합이 의심되어 max_depth값을 낮추어 다시 테스트하니 0.93이 나온 것을 알 수 있었습니다. 따라서 과적합과 같은 경우를 고려하기 위하여 과적합을 줄일 수 있는 요소를 찾아보았습니다.

https://greeksharifa.github.io/machine_learning/2019/12/09/Light-GBM/http://machinelearningkorea.com/2019/09/29/lightgbm-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0/를 참고하여 사용할 파라미터를 선정하였습니다.

 

그리고 여러 parameter들을 종합적으로 테스트를 하면 각 요소들이 얼만큼 차이를 내는지 파악하기 힘들어 parameter 하나씩 테스트를 하였습니다.

 

 

다음과 같이 범위를 좁혀나가며 best Parameter에 근접한 범위로 좁혀가면서 최적 값을 찾아보았습니다. 그리고 과적합을 조절할 파라미터들은 max_depth와 함께 테스트하였습니다.

하지만 다른 파라미터들과 함께 테스트하였을 때 좋지 않은 결과를 보여주기도 하였습니다.

 

사이트를 통하여 테스트시 0.93

 

 

적절한 max_depth를 찾으려 하였으나, 초기에 max_depth값 테스트를 해보기위해 설정했던 max_depth = 90, learning_rate = 0.1, n_estimators = 300이 가장 좋은 결과를 보여주었습니다. 아마 과적합이 일어나면서 확률이 좋아진 것으로 예상합니다. 과적합을 줄이면서 좋은 성능을 내는 파라미터를 찾기 어려웠습니다. 따라서 n_iter의 값을 늘리고 max_depth, n_estimators의 값을 줄여서 테스트 하였습니다.

여러 번 testset으로 예측한 결과 max_depthlearning_rate, n_estimators의 값을 변경한 경우가 0.93으로 더 좋은 예측을 보여주어 다른 값보다 이 3가지 값을 변경시켜 더 테스트 해보기로 하였습니다. 범위를 넓히고 과적합을 줄이기 위해 범위를 줄이면서, n_iter1000으로 늘려 여러 값들을 테스트해보았습니다.

그래도 변화가 없어 0.43%가 나왔던 범위를 선택하고 나머지 parameter들을 추가하여 다시 테스트해 보았습니다. 

0.92로 향상은 없었습니다.

Hyper parameter값들을 여러가지로 조정해보고 testset을 적용하여 정확도를 보았을때, acc : 0.929039301310044 가 가장 좋은 결과를 보여주었습니다.

 

###HYPERPAMETER TUNING####
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
# Model comparison 
import matplotlib.pyplot as plt
from sklearn import model_selection
# from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import LabelEncoder
from xgboost import XGBClassifier
import lightgbm as lgb
from lightgbm import LGBMClassifier
from bayes_opt import BayesianOptimization
from hyperopt import fmin, tpe, hp

import pandas as pd
import numpy as np
import pprint as pp

'''
HI, PH, GR, PH, EL, MI, PH, MI, CO, EL, GR....
1. feature selecion

2. algorithm selection

3. hyper parameter tuning
randomizedserchcv 가 조합을 자동으로 골라주고, 시간이 줄어드므로 사용함.
'''

#1. 데이터 셋 준비
data = pd.read_csv('C:\dataset/trainset.csv')

#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]

data_x
# train, test 나눔
train_X, test_X, train_y, test_y = train_test_split(data_x, data_y, test_size=0.3, random_state=1234) 


base_model = LGBMClassifier(random_state=1234)
base_model.fit(train_X, train_y)
base_accuracy = base_model.score(test_X, test_y)
print(base_accuracy)

n_estimators = [int(x) for x in np.linspace(start = 200, stop = 600, num = 41)]
# Maximum number of levels in tree
max_depth = [int(x) for x in np.linspace(1, 400, num = 41)]
#하나의 트리가 가지는 최대 리프 개수
#num_leaves = [int(x) for x in np.linspace(2, 1000, num = 31)]

#리프 노드가 되기 위한 최소한의 샘플 데이터 수
#min_child_samples  = [int(x) for x in np.linspace(1, 100, num = 11)]

learning_rate = [float(x) for x in np.linspace(0.000001, 0.5, num = 41)]



#데이터 샘플링 비율 0이되면 안됨
#bagging_fraction = [float(x) for x in np.linspace(0.1, 1, num = 11)]

#개별 트리 학습시 선택되는 피처 비율 - 과적합 방지
#feature_fraction = [float(x) for x in np.linspace(0.000001, 1, num = 11)]

#과적합을 제어하기 위해 데이터를 샘플링하는 비율
#subsample  = [float(x) for x in np.linspace(0.000001, 1, num = 11)
#metric = ['multiclass']

# Create the random grid
random_grid = {'n_estimators' : n_estimators,
               'max_depth' : max_depth,
               #'feature_fraction': feature_fraction,
               #'subsample' : subsample,
               'learning_rate' : learning_rate
               #'bagging_fraction' : bagging_fraction,
               #'num_leaves' : num_leaves,
               #'min_child_samples' : min_child_samples,
              # 'metric' : metric
               }

pp.pprint(random_grid)


'learning_rate' : learning_rate
               #'bagging_fraction' : bagging_fraction,
               #'num_leaves' : num_leaves,
               #'min_child_samples' : min_child_samples,
              # 'metric' : metric
               }

pp.pprint(random_grid)

# Use the random grid to search for best hyperparameters
rf = LGBMClassifier(random_state=1234)
rf_random = RandomizedSearchCV(estimator = rf, param_distributions = random_grid, n_iter = 1000, cv = 5, verbose=2, random_state=42, n_jobs = -1)

# Fit the random search model
rf_random.fit(train_X, train_y)

# best parameters
# best_params에 최적 조합이 저장됨
pp.pprint(rf_random.best_params_)


# best model
#best_estimator => 최적 조합을 적용해서 만들어진 모델
best_random_model = rf_random.best_estimator_
best_random_accuracy = best_random_model.score(test_X, test_y)

print('base acc: {0:0.2f}. best acc : {1:0.2f}'.format( \
base_accuracy, best_random_accuracy))
print('Improvement of {:0.2f}%.'.format( 100 * \
(best_random_accuracy - base_accuracy) / base_accuracy))

 

 

######testset save to csv#######
from lightgbm import LGBMClassifier
import pandas as pd
import numpy as np

#1. 데이터 셋 준비
data = pd.read_csv('C:\dataset/trainset.csv', header=None)
test_x = pd.read_csv('C:\dataset/testset.csv', header=None)

data.shape
test_x.shape
#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]

data_x
data_y

model = LGBMClassifier(learning_rate = 0.1, max_depth = 90, n_estimators = 300)
model.fit(data_x, data_y)

pred_y = model.predict(test_x)

result = pd.DataFrame(pred_y)
result.to_csv('lightgbm.csv', header=None, index=False)

 

 

후기)

먼저 그래프로 모델을 비교하여 해당 데이터에 어떤 모델이 가장 잘 맞는지 고르는 것이 전반적인 예측율에 많은 영향을 끼친다고 느꼈다. 그리고 적절한 feature을 찾기 위해 시간이 빠른 모델을 사용하여 테스트를 하면 시간을 줄일 수 있고 hyper parameter를 찾기 위한 여러가지 방법들을 알게 되었다.

 

이번 경진대회에서는 RandomizedSearchCV를 사용하였다. 이 방법으로 적절한 hyper parameter를 찾기 위해 parameter 별로 값을 바꾸어 테스트를 해보고, 여러 parameter들을 동시에 바꾸어 가며 테스트를 하였다.

또한 n_iter을 높일수록 과적합을 줄여 향상이 더 줄어들 수 있다는 것도 알게 되었다. 하지만 적절한 값을 찾는 것이 매우 힘들었다. Parameter를 바꿀 때 이것이 향상되었는지 과적합인지, 과소적합인지를 구분하기가 힘들었다.

처음에 1.38%의 향상을 보았지만 그 값은 과적합으로 인해 예측은 좋지 못하였고, 오히려 max_depth를 낮추니 결과가 좋아지는 경우를 보았다. 또한 test_size 비율을 바꿔가며 나온 결과값을 테스트해보았지만 좋은 결과를 얻기는 어려웠다.

따라서 이런 튜닝을 하는 과정은 소모적이며 때론 2시간 이상이 걸릴 만큼, 시간이 많이 들고 적절한 값을 찾는 것은 감에 의존하고 우연에 의존한다는 생각을 하였다. 이런 과정을 편하게 해주는 방법들이 없을까 찾아보았고, hyper parameter가 변경될 때마다 정확도의 변화를 그래프로 보여주던가, 과적합을 판단할 수 있게 과적합 수치도 함께 보여준다면 더 편리할 것이라 생각하였다.

 

AutoML은 데이터의 특성에 따라 좋은 알고리즘과 어울리는 파라미터들을 자동화하여 찾아준다.

그 중 Auto-sklearn라는 방법이 있다. 데이터가 들어오면, 데이터에 맞을만한 알고리즘, parameter를 알려주는 meta-learning process를 진행하고 이 결과로 알고리즘과 parameter set들을 추천해 준다. 그 후 앙상블 기법을 활용해 추천된 알고리즘, parameter set들의 최적화를 진행합니다. 하지만 Anaconda does not ship auto-sklearn, and there are no conda packages for auto-sklearn” 와 같은 답변을 얻어 실제로 해보진 못하였다.

그리고 Bayesian Optimization을 통하여 hyper parameter의 최적값을 탐색할 수 있다. Bayesian Optimization은 매 회 새로운 hyper parameter값에 대한 조사를 수행할 시, 사전지식을 충분히 반영하면서 전체적인 탐색 과정을 체계적으로 수행할 수 있는 방법론이다. 따라서 이 방법을 통하여 hyper parameter를 찾으려 하였다. 하지만 완벽히 이해하지 못하였고, 관련 자료를 많이 찾지 못하여 사용법과 에러에 대한 원인을 찾지 못하였다.

728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

흉부 X-ray 사진으로 폐렴 진단 모델  (0) 2021.05.09
CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
딥러닝 4  (0) 2020.10.29
딥러닝 3  (0) 2020.10.09
딥러닝 2  (0) 2020.09.29
블로그 이미지

아상관없어

,
반응형

간단한 android game app

 

Mono Runtime 가상머신에서 사용하는 중간 언어인 CIL이 있는 dll파일들을 디컴파일하였다.

Assembly-CSharp.dll 파일이 C# 개발자 코드의 컴파일 결과이므로 dnSpy 프로그램을 사용하여 Assembly-CSharp.dll을 수정하였다.

먼저 CompleteProject 파일 안의 정보들을 보고 “Player~~~~” 관련 코드가 플레이어와 관련된 코드라 추측을 하였다. 그리고 각각 “Movement”, “Shooting”, “ScoreManager” 코드에서 변수 이름으로 관련 변수들이 의미하는 것을 추측하였다.

그 후 해당 변수에 들어가 있는 값들을 수정해 주었으나, 실제 게임 구동 시 적용이 되질 않았다.

ctrl+shift+R 키를 통하여 해당 변수가 사용되는 함수들을 찾아보고 해당 함수안에서 변수에 곱을 하여 값을 조작하여 Damage, Speed, Score, Heath를 조절하였다.

 

- Damage 조절

 

- Speed 조절

 

- startHealth 조절

- Score 조절

 

실행 결과

 

[방어 방법]

이러한 해킹을 막기위해선 ProGuardDexGuard와 같은 소스코드 난독화 도구를 사용하여 소스코드를 난독화한다. Renaming(클래스 및 메소드 이름 변경), Control Flow(제어 흐름 변환), String Encryption(문자열 암호화), API Hiding(API 은닉), Class Encryption(파일 내용 전체를 암호화하였다가 동적으로 복호화), Dex Encription(Dalvik Executable 파일 암호화)같은 기법을 사용하여 APK파일을 디컴파일하더라도 코드를 읽기 난해하게하여 공격을 어렵게 만든다.

 

원본 apk파일의 해쉬값을 서버에 저장하여 설치된 apk의 해쉬값과 비교하여 동일한지 판단하여 유효성을 체크한다.

앱에 서명을 하여 원본 서명과 설치된 앱 간의 서명을 비교하여 위변조한 앱인지 체크한다.

Apk 파일에 META-INFapk 배포시 서명한 내용이 들어가는데 파일을 변조할 경우 패키지 손상오류가 뜨며 기기에 설치되지 않는다. apk파일을 리패키징할 때 서명을 해주지 않아 설치가 되지 않는다.

에뮬레이터의 경우 root권한이 설정되어 있어 이를 우회하는 것으로 생각하였으나, root권한을 끈 경우에도 설치가 되는 것으로 보아 에뮬레이터는 앱의 서명을 확인하지 않는 것으로 생각된다.

 

인터넷 검색을 통하여 앱 서명이 이루어지지않은 앱을 구하여 테스트를 해보았다.

서명을 하지 않은 앱들은 실기기(galaxy note5 Android 7.0)에서 패키지가 손상된 것 같습니다라는 에러가 뜨면서 설치가 되지 않는다.

 

반면 LD player의 경우 두 앱이 잘 설치가 된다.

따라서 LD player의 경우 앱 서명 체크를 하지않아 설치가 된다고 생각을 하였다.

728x90
반응형
블로그 이미지

아상관없어

,
반응형

[프로그램 동작]

retlib.c

Badfile을 읽어서 bof의 인자로 전달해준다. Bof 함수는 badfile을 읽고 buffer에 쓰는데 경계체크를 하지 않으므로, 버퍼의 크기를 초과해서 쓰게 된다.

이 곳이 retlib파일의 취약점이 된다.

따라서 버퍼 오버플로우를 일으켜 bof함수의 리턴주소를 system함수로 조작할 수 있게 된다.

 

exploit.c

Exploitbadfile을 열고 buf를 쓴다. Retlibbuffer over flow 취약점을 이용하므로, retlibbof 함수의 return 주소에 system 함수의 주소를 넣고, 인자로 “/bin/sh”을 준다.

그리고 return 주소로 exit를 준다. 따라서 bof함수가 정상적으로 return 되지 않고 system 함수를 호출하고 인자로 “/bin/sh”을 넘겨주어 shell이 실행되게 된다.

RetlibsetUID가 설정되어있고, Non-executable stack이므로 code reuse 공격을 사용하여 libcsystem함수를 이용하여 /bin/shroot권한으로 실행한다.

 

 

Retlib.c bof함수를 disassemble하여 보면 버퍼 위로 더미데이터가 8바이트가 있는 것을 알 수 있고, 따라서 bof함수의 리턴주소의 위치는 buffer[24]임을 알 수 있다.

따라서 리턴 주소를 조작할 수 있게 된다.

그리고 fread하기전 인자들을 전달하는 것을 볼 수 있다.

[ebp+0x8] =badfile의 주소, 0x12c = 300, 0x1 = sizeof(char), [ebp-0x14] = buffer의 시작주소를 전달하는 것을 볼 수 있다.

buffer[24]의 위치는 원래 return address이므로 여기에 system의 주소를 넣고 그 위(buffer[28]) exit의 주소, 그 위(buffer[32]) /bin/sh의 주소를 넣어준다.

 

gdb에서 printfind 함수를 이용해 system함수의 위치는 0xb7e42da0, exit 함수의 위치는 0xb7e369d0, “/bin/sh”의 위치는 0xb7f6382b임을 알 수 있다. 따라서 다음과 같이 exploit.c를 작성하였다.

 

Exploit을 실행하고 retlib을 실행하면 스택이 다음과 같이 바뀌게 된다.

Bof의 리턴주소 = system함수의 주소 -> system함수 호출

Bof 리턴주소 위 4byte = exit 함수의 주소 -> 호출된 system 함수의 리턴 주소가 된다.

Bof 리턴주소 위 8byte = /bin/sh의 주소 -> 호출된 system 함수의 인자로 들어가게된다.

 

retlibbof에서 오버플로우가 발생하고 위와 같이 덮여 쓰여지게 된다.

Non executable stack이라 하더라도 executable code region system함수를 불러오므로 shell을 실행할 수 있게 된다.

이 파일은 setuid bit가 설정되어있고 ownerroot이므로 root의 권한으로 실행되게 된다.

따라서 ruidseed이지만 euid root임을 알 수 있다.

 

[취약점 보완]

컴파일러 수준에서 스택 쉴드를 사용한다. Shadow 스택을 사용하여 함수가 리턴될 때 call stack, shadow stack을 비교하여 일치하지 않을 경우 종료하게 한다.

 

- ASLR을 이용하여 주소를 랜덤화 한다.

 

- 스택 가드기법(-fstack-protector)를 사용하여 스택 변수와 스택 프레임 포인터 사이에 보호값을 넣는다.

 

- 프로그래머가 명시적으로 복사할 크기를 지정해주어 버퍼 오버 플로우가 일어나지 않게 한다.

fread(buffer, sizeof(char), 12, badfile)을 하여 12바이트만 읽어오게 한다.

또는 버퍼의 크기를 badfile의 크기보다 크게 설정해준다.

 

- 코드로 리턴주소와 버퍼 사이에 guard를 설정하여 값이 변경되었는지 확인한다.

이 방법은 공격을 막을 순 있으나, bof 스택 내의 버퍼와 리턴주소 사이를 건드려야하므로, 정상적으로 “Returned Properly”를 출력하지 않고 프로그램이 종료된다.

 

- DashsetUID 프로세스 내에서 권한이 내려가듯 위험한 코드가 실행되기전 권한을 낮추어 버린다.

이 방법도 공격을 막을 순 있으나 bof 함수를 실행을 막지는 못하므로 정상작동하진 않는다.

728x90
반응형
블로그 이미지

아상관없어

,
반응형

[프로그램 동작]

Exploit.c에서 badfilebuffer를 쓴다. 그리고 stack.c에서 badfile를 열고 str에 읽는다. Badfile의 값이 써진 strbof의 인자로 넘겨준다.

Stack.c에서 bof 함수는 인자로 받은 strbuffer에 복사한다. 하지만 strcpyNULL을 만나기 전까지의 문자열을 복사하고 복사할 문자열의 길이는 검사하지 않는다. 따라서 buffer의 크기가 24이고, str의 길이는 517이므로 buffer의 스택을 넘어선다.

이때 bof 함수의 return addressshellcode의 주소를 넣어 shellcode가 실행되게 한다.

 

Gdb를 통해 strcpy가 실행되는 곳에 break를 하였고, bof함수를 disas하여 strcpy0x20크기의 buffer인자가 전달되는 것을 알 수 있다.

따라서 buffer의 크기는 32byte임을 알 수 있다.

 

gdb를 통하여 ebp0xbfffeab8임을 알 수 있고, ebp의 주소에서 0x20만큼 빼주어 buffer의 시작 위치를 알 수 있다. 그리고 이를 토대로 bof return address가 실제와 일치하는지 disas main을 하여 비교를 하면 0x08048574로 같음을 알 수 있다.

 

Buffer의 크기는 32이고 saved edp for bof의 크기는 4이므로 buffer[36]부터가 return address of bof임을 알 수 있다. Exploit.c에서 “memcpy(buffer+sizeof(buffer)-sizeof(shellcode), shellcode, sizeof(shellcode));”를 하여, buffer의 맨 끝에 shellcode를 넣었다.

따라서 정확한 shellcode의 주소를 몰라도 return address 이후와 buffer 이전의 아무 주소 값이나 return address of bof에 넣어준다면 shellcodebuffer의 맨 끝에 있으므로 실행이 될 것이다.

시스템이 Little endian이므로

주소값을 반대로 넣어준다. Buffer의 크기는 32byte이고 saved ebp or bof 4byte이므로 *(buffer +36)return address를 가리키므로, *(buffer +36)부터 차례로 주소를 넣어준다.

이것을 실행하면 원하는 shellcode가 동작하는 것을 볼 수 있다.

 

 

[취약점 메모리 구조]

Bof 함수의 strcpy(buffer, str)이 취약점이다. 먼저 bof 함수 인자인 str이 쌓이고 그 다음에 Return Address of bof, Saved ebp of bof, buffer가 쌓인다. Buffer32byte이고 saved ebp of bof4byte, return address of bof 4byte, str 517bye이다.

Str의 크기가 buffer보다 크고, strcpy는 문자열의 길이를 체크하지 않으므로 str의 값들이 buffer스택 위로 덮어쓰여진다.

 

- Exploit 실행 후 메모리 구조

Exploit이 실행되면, overflow로 인하여 bofreturn address0xbfffeb68(return address 위의 랜덤주소, buffer의 마지막에 shellcode가 있다)이 들어간다.

그리고 NOP 명령어가 실행되다가 buffer의 끝에 있는 shellcode를 실행한다.

 

[취약점 보완]

프로그래머가 스택의 다른 영역을 침범하지 않게 코드상으로 영역을 명확히 명시하거나 입력 받는 데이터의 크기를 확인하거나 buffer overflow에 취약한 함수를 사용하지 못하게 한다.

 Buffer overflow에 취약하지 않은 함수를 사용한다. Strcpy(buffer, str)strncpy(buffer, str, sizeof(buffer)-1)함수로 대체 사용하여 복사할 크기를 지정하여 overflow가 생기지 않도록 한다.

 

 

Strncpy를 사용하여 복사할 크기를 지정해주었을 때 공격이 실패하고 정상적으로 “Returned Properly”가 수행되는 것을 알 수 있다.

또는 sizeof(buffer)BUF_SIZE이나 24로 명확하게 적어준다.

 

인자로 받는 데이터의 크기를 체크한다. bof함수의 인자로 int size값을 받아 str의 크기를 체크하여 오버플로우를 방지한다. Bof(char*str, int size)의 형태로 받는다.

크기가 buffer보다 클 때 warning을 출력하고 exit한다.

 

 

스택 쉴드 기법을 사용하여 함수가 호출될 때 그 함수의 Return Address를 특수 스택에 저장을 하고 함수 종료 시 저장해둔 Return Addresss와 비교를 하여 값이 다르면 프로그램을 종료시킨다.

 

해제한 ASLR(Address Space Layout Randomize)기법을 다시 사용하여 각 프로세스 안의 스택이 임의의 주소에 위치하도록 한다.

해제한 NX bit를 활성화하여 스택/힙 영역의 실행권한을 제거하여 쉘의 실행을 방지한다.

해제한 Stack Guard기법을 사용하여 스택에 Canary 값을 넣고 이 값이 변조되었는지 검사하여 오버플로우를 체크한다.

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

간단한 Android game app hacking  (0) 2021.05.03
SEED Lab Return-to-Libc Attack  (0) 2021.05.03
SystemProperties로 에뮬레이터 탐지  (0) 2021.05.03
BOF 원정대 level 16  (0) 2021.05.03
BOF 원정대 level 18  (0) 2021.05.03
블로그 이미지

아상관없어

,
반응형

LDplayer와 여러 디바이스의 property를 비교하여 차이점을 찾으려 하였다.

하지만 각 스마트폰 제조사, 모델에 따라 각기 다른 property명과 값을 가지고 있어 범용적으로 기기가 real device인지 emulator인지 구분하기 힘들었다.

또한 확실히 구분되는 아키텍쳐 정보는 x86기반의 안드로이드 기기가 나오면서 이것으로 구분하기는 힘들었다. 따라서 실제 가진 기기의 property정보를 바탕으로 emulator와 비교하여 galaxy note 3LDplayer를 구분했다.

아래 사진을 보면 real device에서는 가지는 property이지만 emulator에선 가지지 않는 property를 정리하였다. 그리고 각 기기별로 그 이름이 다 다른 것을 알 수 있다.

(각 테스트 기기는 galaxy S10, galaxy S9, galaxy Note 3, Xperia Z3 Compact 이다.)

(getprop한 정보를 word에 옮겨 비교하였다.)

[Bluetooth 관련 property]

[GPS 관련 property]

[Camera 관련 property]

 

따라서 위와 같이 공통적이지 않은 property emulator인지 구분할 경우 모든 기기의 property를 다 알고 있지 않은 이상 적용하기 어려워 테스트 기기 한정으로 적용을 시켜 테스트하였다.

(위 프로퍼티를 갖고 있지 않은 다른 디바이스에선 emulator라고 탐지하게 된다.)

boolean isProbablyAnEmulator(){ // checking Emulator
    return get("service.camera.running").equals("") && get("ro.bluetooth.tty").equals("");
}

 

 

property외에 usim 관련, 네트워크 관련 property들은 공통적인 이름을 가지고 있으면서 다른 값을 가지는 것을 확인하였다.

[gsm.sim.state]: [NOT_READY] - LDplayer

[gsm.sim.state]: [LOADED] – s10

[gsm.sim.state]: [LOADED] – s9

[gsm.sim.state]: [READY] – note 3

[gsm.sim.state]: [ABSENT] – Xperia z3 compact

컴퓨터 A

컴퓨터 B

Galaxy Note 3

[dhcp.eth0.gateway]: [172.16.2.2]

[dhcp.eth0.ipaddress]: [172.16.2.15]

[dhcp.eth0.leasetime]: [86400]

[dhcp.eth0.mask]: [255.255.255.0]

[dhcp.eth0.mtu]: []

[dhcp.eth0.pid]: [1735]

[dhcp.eth0.reason]: [REBOOT]

[dhcp.eth0.result]: [failed]

[dhcp.eth0.server]: [172.16.2.2]

 

[dhcp.eth0.gateway]: [172.16.2.2]

[dhcp.eth0.ipaddress]: [172.16.2.15]

[dhcp.eth0.leasetime]: [86400]

[dhcp.eth0.mask]: [255.255.255.0]

[dhcp.eth0.mtu]: []

[dhcp.eth0.pid]: [1689]

[dhcp.eth0.reason]: [REBOOT]

[dhcp.eth0.result]: [failed]

[dhcp.eth0.server]: [172.16.2.2]

 

[dhcp.wlan0.gateway]: [192.168.0.1]

[dhcp.wlan0.ipaddress]: [192.168.0.18]

[dhcp.wlan0.leasetime]: [7200]

[dhcp.wlan0.mask]: [255.255.255.0]

[dhcp.wlan0.mtu]: []

[dhcp.wlan0.pid]: [25465]

 

Real Device는 대부분 무선 인터넷환경(wlan)을 이용하니 이 부분을 확인하면 좀 더 쉽게 emulator를 탐지할 수 있을 거라 생각한다. 그리고 LDplayer의 경우 eth0을 사용하고, 다른 컴퓨터 환경에서도 같은 gateway, ipaddress를 가지는 등 이 정보를 가지고도 판단할 수 있을 거라 생각한다.

 

하지만 해당 정보들 모두 최신 emulator에서 값을 조정할 수 있기 때문에, 완벽한 방법은 아니다. 

 

 

 

 


(adb shell getprop를 하였을 때 수업시간에 배운 selinux가 실제 안드로이드 디바이스에 적용이 되있음을 알 수 있었다.)

728x90
반응형
블로그 이미지

아상관없어

,