반응형

 

1부2부 포스팅을 보시면 이해가 쉽습니다.

이번 포스팅에서는 인증서를 Burp Suite 에 import 해서 사용하는 방법을 담고 있습니다.

 

 

 

1부 포스팅에서 준비한 인증서 파일들 중 .der 파일과 .pkcs8 파일이 필요합니다.

 

 

그 다음, Burp Suite 를 실행해서 Proxy 탭의 Proxy Settings 메뉴를 클릭합니다.

 

 

 

 

 

설정 창에서 Import / export CA certificate 버튼을 클릭합니다.

 

 

 

반응형

 

 

아래 옵션을 선택해주세요.

 

 

 

 

 

 

파일 선택 버튼이 두 개가 보이는데, 위에는 .der 파일을, 아래에는 .pkcs8 파일을 넣고 진행해줍니다.

 

 

 

 

위 과정을 성공적으로 마치면 안드로이드 단말기에서

사설 인증서를 시스템 인증서로 권한 상승을 한 후

Burp Suite 에서 Proxy 가 정상적으로 동작하는 것을 확인할 수 있을겁니다 :)

반응형
반응형
반응형

인증서를 만들지 않으신 분들은 이전 포스팅을 참고해주시기 바랍니다.

해당 포스트에서는 생성한 인증서를 안드로이드 단말기에 설치하는 내용을 담고 있으며, 루팅된 환경에서 진행했습니다.

 

 

 

가장 먼저, 생성해둔 인증서를 단말기로 옮깁니다.

cmd)

adb push 1127f18c.0 /sdcard/

 

 

 

설치 과정은 Android 14 를 기준으로 나뉩니다.

 

 

Android 14 미만 단말기에서의 설치

 

먼저, 기존에 설치되어 있는 인증서를 백업합니다.

(백업할 위치는 적절히 수정해줍니다)

adb shell)

cp /system/etc/security/cacerts/* /data/local/tmp/mycerts/

 

 

미리 생성해두었던 인증서를 옮깁니다.

(인증서의 파일명은 다를 수 있습니다)

adb shell)

mv /sdcard/1127f18c.0 /data/local/mycerts

 

 

인증서 영역을 mount 합니다.

adb shell)

mount -t tmpfs tmpfs /system/etc/security/cacerts

 

 

백업한 인증서와 새로 설치할 인증서가 담긴 경로를 덮어씌웁니다.

adb shell)

cp -f /data/local/tmp/mycerts/* /system/etc/security/cacerts/

 

 

권한을 설정해줍니다.

adb shell)

chown root:root /system/etc/security/cacerts/*
chmod 644 /system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*

 

 

 

Android 14 이상 단말기에서의 설치

 

 

Android 14 이상 단말기부터는 아래 Maigsk Module 을 이용해서 설치하면 간단합니다.

 

https://github.com/WindSpiritSR/CustomCACert

 

GitHub - WindSpiritSR/CustomCACert

Contribute to WindSpiritSR/CustomCACert development by creating an account on GitHub.

github.com

 

간단히 과정을 설명해드리자면, 생성한 인증서를 모듈의 system/etc/security/cacerts 경로에 넣고 Magisk 앱을 통해 모듈을 설치하면 됩니다.

 

 

다음 포스팅은 Burp Suite 에서 위 인증서를 사용하는 방법을 담겠습니다 :)

반응형
반응형
반응형

본 과정은 윈도우에서 진행되었으며 openssl 이 설치되어 있다는 가정하에 진행합니다.

해당 포스트에서는 인증서를 생성하는 단계까지의 내용만 담고 있습니다.

 

 

 

먼저 아래의 openssl.cnf 파일을 준비합니다.

(TEST 에 해당하는 부분은 적절히 변경해줍니다)

# openssl.cnf

[ req ]
default_bits			= 2048
default_md			= sha256
default_keyfile			= digi_cert.key
distinguished_name		= req_distinguished_name
extensions			= v3_ca
req_extensions			= v3_ca

[ v3_ca ]
basicConstraints       = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier   = hash
keyUsage               = keyCertSign, cRLSign
nsCertType             = sslCA, emailCA, objCA

[ req_distinguished_name ]
countryName                     = Country Name
countryName_default             = KR
countryName_min                 = 2
countryName_max                 = 2
organizationName                = TEST
organizationName_default        = TEST
organizationalUnitName          = TEST
organizationalUnitName_default  = TEST
commonName                      = TEST
commonName_default              = TEST
commonName_max                  = 64

 

 

위 openssl.cnf 파일을 이용해서 private key 를 생성합니다.

(기간, 파일 이름 등 적절히 변경해줍니다)

# Create a private key.

openssl req -x509 -days 365 -nodes -newkey rsa:2048 -outform der -keyout server.key -out cert.der -extensions v3_ca -config openssl.cnf

 

 

private key 를 pkcs8 포맷으로 변환합니다.

# Convert key to pkcs8 format

openssl rsa -in server.key -inform pem -out server.key.der -outform der
openssl pkcs8 -topk8 -in server.key.der -inform der -out server.key.pkcs8.der -outform der -nocrypt

 

 

cert.der 을 pem 포맷으로 변환합니다.

# Convert DER to PEM

openssl x509 -inform DER -in cert.der -out cert.pem

 

 

인증서의 hash 값을 추출합니다.

# get hash from cert

openssl x509 -inform PEM -subject_hash_old -in cert.pem
  => 1127f18c

첫 번째 줄을 복사한다.

 

 

hash 값을 이용해 cert.pem 의 이름을 변경합니다.

# rename to [HASH].0

move cert.pem 1127f18c.0

 

 

 

실질적으로 1127f18c.0 파일을 안드로이드 단말기에 설치할 예정입니다.

추후 과정은 다음 포스팅을 확인해주세요 :)

반응형
반응형

사용자 환경 : macOS Sierra 10.12.6Android Studio 3.0.1 {

  Build #AI-171.4443003, built on November 10, 2017

  JRE: 1.8.0_152-release-915-b08 x86_64

  JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

  }






이번에는 커스텀 리스트뷰에 대해 알아보고자 한다.



먼저 이 앱의 최종 화면은 다음과 같다.





각 아이템을 클릭 시 맨 우측에 좋아요 숫자가 올라가는 기능도 구현할 예정이다.



1. 프로젝트를 생성한다.




2. 해당 파일을 받고 앞축을 푼 후 android 폴더에 있는 다음 폴더들을 전부 복사한다.

ic_thumb_up_black_18dp.zip



2-1. 다시 안드로이드 스튜디오로 돌아와 프로젝트 뷰로 변경 후 다음 경로를 찾아 복사한다.





2-2. res 폴더를 클릭후 복사(Ctrl + v)한다.



이로써 개발에 앞서 모든 준비가 완료되었다. 본격적으로 코딩을 시작해보자.




3. 리스트뷰에 사용될 아이템을 지닌 클래스를 생성한다. ListviewItem.java

public class ListviewItem {

    private String strName;
    private int nId, nLike;

    public String getStdName() {
        return stdName;
    }

    public void setStrName(String strName) {
        this.strName = strName;
    }

    public int getId() {
        return nId;
    }

    public void setId(int nId) {
        this.nId = nId;
    }

    public int getLike() {
        return nLike;
    }

    public void setLike(int nLike) {
        this.nLike = nLike;
    }
}

line 3. strName은 최종 실행화면의 C, Java 등을 나타내는 제목이다.


line 4. nId, nLike는 역시 최종 실행화면의 맨 좌측과 우측의 숫자를 나타낸다.





4. 리스트뷰 레이아웃 설정한다. layout_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="1">

    <TextView
        android:id="@+id/txt_id"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.1"
        android:gravity="center"/>

    <TextView
        android:id="@+id/txt_name"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.7"
        android:textStyle="bold"
        android:gravity="center"/>

    <ImageView
        android:id="@+id/img_up"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.1"
        android:gravity="center"
        android:src="@drawable/ic_thumb_up_black_18dp"/>

    <TextView
        android:id="@+id/txt_like"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.1"
        android:gravity="center"/>
</LinearLayout>





5. 리스트뷰를 사용할 어댑터 클래스를 생성한다. ListviewAdapter.java

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class ListviewAdapter extends BaseAdapter {

    private ArrayList<listviewitem> arrayList;
    private int nId;

    public ListviewAdapter() {
        arrayList = new ArrayList<listviewitem>();
        nId = 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        final Context context = viewGroup.getContext();

        ListviewItem listItem = arrayList.get(i);

        if (view == null) {
            LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.layout_listview, viewGroup, false);
        }

        TextView id = (TextView)view.findViewById(R.id.txt_id);
        TextView name = (TextView)view.findViewById(R.id.txt_name);
        TextView like = (TextView)view.findViewById(R.id.txt_like);

        id.setText(String.valueOf(listItem.getId()));
        name.setText(listItem.getStdName());
        like.setText(String.valueOf(listItem.getLike()));

        return view;
    }

    public void addItem(String name) {
        ListviewItem item = new ListviewItem();

        item.setId(++nId);
        item.setStdName(name);
        item.setLike(0);

        arrayList.add(item);
    }

    @Override
    public int getCount() {
        return arrayList.size();
    }

    @Override
    public Object getItem(int i) {
        return arrayList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }
}





6. activity_main.xml을 레이아웃 설정한다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.ahn.customlistview.MainActivity">

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ListView>

</LinearLayout>





7. 마지막으로 메인 액티비티에서 기능을 구현해보자.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    private String[] lang = {
            "C",
            "Java",
            "PHP",
            "Swift"
    };

    private ListView listView;
    private ListviewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        adapter = new ListviewAdapter();

        listView = (ListView)findViewById(R.id.listview);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View v, final int position, long id) {
                // get item
                ListviewItem item = (ListviewItem)parent.getItemAtPosition(position);

                int getLike = item.getLike();
                item.setLike(++getLike);
                adapter.notifyDataSetChanged();
            }
        });

        initList();
    }

    public void initList() {
        for(int i=0; i<lang.length; i++) {
            adapter.addItem(lang[i]);
            adapter.notifyDataSetChanged();
        }
    }
}

line 9~14. 리스트뷰에 사용될 아이템 제목들이다.


line 27. 전에 생성했던 어댑터를 리스트뷰에 세팅한다.


line 32. 리스트를 클릭 시 해당 아이템의 번호를 인덱스로 하여 참조를 얻는다.


line 34~36. 좋아요를 +1 시키는 작업을 하고나서 데이터가 변경되었음을 알린다.


line 43. C, Java 등을 리스트에 추가한다.





이로써 커스텀 리스트뷰를 사용할 수 있게 되었다.

반응형
반응형

사용자 환경 : macOS Sierra 10.12.6Android Studio 3.0.1 {

  Build #AI-171.4443003, built on November 10, 2017

  JRE: 1.8.0_152-release-915-b08 x86_64

  JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

  }






현재 로그인 시스템이 구현되어 있는 대부분의 앱에는 자동 로그인 기능이 구현되어 있다.



자동 로그인 기능이 구현되어 있지 않은 앱을 사용해본 경험이 있다면 이 기능을 사용함으로써 앱이 많은 편리함을 가져다 준다는 것을 알 수 있다.



이 기능을 구현하기 위해 우리는 SharedPreference API를 사용할 것이다.



1. 가장 먼저 정보를 저장하기 위한 메소드를 내장한 클래스를 구현한다.

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

public class SaveSharedPreference {

    static final String PREF_USER_NAME = "username";

    static SharedPreferences getSharedPreferences(Context ctx) {
        return PreferenceManager.getDefaultSharedPreferences(ctx);
    }

    // 계정 정보 저장
    public static void setUserName(Context ctx, String userName) {
        SharedPreferences.Editor editor = getSharedPreferences(ctx).edit();
        editor.putString(PREF_USER_NAME, userName);
        editor.commit();
    }

    // 저장된 정보 가져오기
    public static String getUserName(Context ctx) {
        return getSharedPreferences(ctx).getString(PREF_USER_NAME, "");
    }

    // 로그아웃
    public static void clearUserName(Context ctx) {
        SharedPreferences.Editor editor = getSharedPreferences(ctx).edit();
        editor.clear();
        editor.commit();
    }
}

line 7. key 값에 해당된다.


line 9~11. 모든 액티비티에서 인스턴스를 얻기 위한 메소드이다.


line 14~18. 로그인 시 자동 로그인 여부에 따라 호출 될 메소드이다. userName이 저장된다.


line 21~23. 현재 저장된 정보를 가져오기 위한 메소드이다.


line 26~30. 자동 로그인 해제 및 로그아웃 시 호출 될 메소드이다.





2. 자동 로그인 여부를 체크할 인증용 액티비티 생성.

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class FirstAuthActivity extends AppCompatActivity {

    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first_auth);

        if(SaveSharedPreference.getUserName(FirstAuthActivity.this).length() == 0) {
            // call Login Activity
            intent = new Intent(FirstAuthActivity.this, LoginActivity.class);
            startActivity(intent);
            this.finish();
        } else {
            // Call Next Activity
            intent = new Intent(FirstAuthActivity.this, HomeActivity.class);
            intent.putExtra("STD_NUM", SaveSharedPreference.getUserName(this).toString());
            startActivity(intent);
            this.finish();
        }
    }
}

line 15~20. SharedPreference에 저장되어 있는 정보의 길이가 0일 경우, 즉 없을 경우 로그인 액티비트를 호출한다.


line 20~26. 나머지 경우, 즉 저장되어 있는 정보가 있을 경우 바로 로그인 다음 액티비티를 호출한다.





3. 자동 로그인 설정 시 사용할 코드

SaveSharedPreference.setUserName(LoginActivity.this, editId.getText().toString());

로그인 액티비티에서 자동 로그인 설정과 함께 로그인 시 EditText의 값을 SaveSharedPrefernce.setUserName(Context, String) 메소드를 통해 저장.

반응형

+ Recent posts