fun25에서 1차 도메인과 서브 도메인도 지정해준다. 그래야지 default port를 사용할 수 있다. fun25는 좀 특이하게 내부아이피 이용으로 프락시서버 등록이랑 포트포워딩 자동화해놔서 ssh 접속할 때도 포트를 22가 아니라 외부포트를 지정해서 접속한다 ㅋㅋ;
fun25 세팅
리버스 프록시로 ctfd는 8000포트를 이용해서 ctf.sung.pw로 서브도메인을 사용하게끔하면 된다.
그리고 CustomLog를 설정할 수 있다. 이게 뭐냐면 ctf.sung.pw에서 발생하는 로그가 /var/log/apache2/access.log 경로에 작성되지 않고 ctf_log/access.log에 로그가 남게된다. 이건 구분할 수 있어서 유용하게 사용할 수 있고 좋은 점 같다.
그래서 $ tail -f /var/log/apache2/access.log로 확인해보면 sung.pw에서 발생하는 로그만 남게된다!
무슨 CTF였더라.. 대충 재밌었던 Level들만 정리 레벨은 아마 1부터15까지 있었나? 명령어도 한정되어서 재밋엇다..
/*
https://del.dog/asm-hell.txt
Command Description
MOVE A1 A2 A1 is the amount of steps (can be negative), A2 is the direction (0 for vertical, 1 for horizontal)
WAIT A1 A1 is the amount of cycles to wait
UNLOCK A1 A1 is the key
READ M1 M1 stores the result of tile read instruction
ADD M1 A1 A2 M1 stores the result of A1 + A2
SUB M1 A1 A2 M1 stores the result of A1 - A2
MUL M1 A1 A2 M1 stores the result of A1 * A2
JMP A1 A1 line in code to be jumped to
JMPZ A1 A2 jump to line A1 if A2 is zero
JMPN A1 A2 jump to line A1 if A2 is negative
CMP M1 A1 A2 M1 stores the result of A1 > A2 (B); A1 > A2: 1, A1 = A2: 0, A1 < A2: -1
*/
Level 8
여기서 주어진 어셈블리 명령에는 div 연산이 존재하지 않아 직접 만들어줘야한다.
왼쪽에 주어진 숫자를 0번 레지스터에 오른쪽에 주어진 숫자를 1번 레지스터에 넣어준다.
0번 레지스터를 계속 1번 레지스터 값으로 빼준 다음에 0번 레지스터에 저장한다. 이렇게 한번 뺄 때마다 5번 레지스터의 값을 1씩 더해준다. 전체적으로 0번 레지스터를 계속 빼주면서 0번 레지스터의 값이 0이 될 때까지 반복해주면 된다.
그리고 키값은 UNLOCK [5]로 카운팅해준 것으로 풀어주면 된다.
Level 12
제일 재밌게 푼 문제이다. 소수판별 문제이다. 우선 c언어로 대충 구상하고 풀었다. 아래 c코드를 옮긴 것이 아래와 같다.
for(int i=2; i<n; i++)
if(n%i==0) MOVE -1 1;
MOVE -1 1;
/*
0 : n
1 : i = 2
2 : 사용 안함
3 : n-1
4 : cmp [6] [0]
5 : cmp [1] [3]
6 : n -> 나머지 연산이 구현되어 있지 않아 [1]로 계속 sub해줌
*/
문제 풀이 과정은 간단하다. 블루스택이나 녹스를 사용할때 루팅으로 후킹해서 문제를 풀려면 루팅체크하는 부분을 우회해서 후킹을 해야한다. 출제자 풀이를 보면 finish 후킹했는데 나는 라이브러리 후킹해서 풀었다. finish 후킹할 생각을 못해서 조금 시간 뺏겼다. 그 이후로는 쉬움!
PS. 문제 풀면서 느낀게 jadx보단 jeb가 훨씬 좋다 ㅇㅇ.. (유료가 최고임)
MainActivity
package com.hspace.pengsu;
import android.os.Bundle;
import android.util.Log;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import b.b.c.h;
import b.b.c.u;
import c.b.a.a.a;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;
public class MainActivity extends h implements View.OnClickListener {
public int o;
public Random p;
public TextView q;
public ProgressBar r;
public ImageButton[] s;
public RootCheck t;
public static final int[] u;
public static int v;
public static {
MainActivity.u = new int[]{0x7F0800B7, 0x7F0800B8, 0x7F0800B9, 0x7F0800BA, 0x7F0800BB, 0x7F0800BC, 0x7F0800BD, 0x7F0800BE}; // id:ib1
MainActivity.v = 0;
}
public MainActivity() {
this.o = 0;
this.p = new Random();
}
@Override // android.view.View$OnClickListener
public void onClick(View arg5) {
int v5 = this.p.nextInt(10);
this.o = v5;
int v1 = MainActivity.v + v5;
MainActivity.v = v1;
if(v1 == 100) {
try {
a.a();
}
catch(Exception v5_1) {
v5_1.printStackTrace();
}
}
if(this.o != 3 && this.o != 5 && this.o != 7 && this.o != 9 && this.o != 10) {
TextView v5_2 = this.q;
StringBuilder v0 = c.a.a.a.a.f("Pengsu\'s Wallet : ");
v0.append(MainActivity.v);
v0.append("$");
v5_2.setText(v0.toString());
this.r.setProgress(MainActivity.v);
return;
}
this.r.setProgress(MainActivity.v);
MainActivity.v = 0;
TextView v5_3 = this.q;
StringBuilder v0_1 = c.a.a.a.a.f("Pengsu\'s Wallet : ");
v0_1.append(MainActivity.v);
v0_1.append("$");
v5_3.setText(v0_1.toString());
}
@Override // b.b.c.h
public void onCreate(Bundle arg6) {
super.onCreate(arg6);
this.s = new ImageButton[8];
this.setContentView(0x7F0B001C); // layout:activity_main
this.q = (TextView)this.findViewById(0x7F0801A0); // id:wallet
this.findViewById(0x7F0801A1); // id:wallet2
this.r = (ProgressBar)this.findViewById(0x7F080128); // id:progress
((u)this.o()).e.setTitle("Make Pengsu earn 100$");
this.q.setText("Pengsu\'s Wallet : 0");
int v0;
for(v0 = 0; v0 < 8; ++v0) {
this.s[v0] = (ImageButton)this.findViewById(MainActivity.u[v0]);
this.s[v0].setOnClickListener(this);
}
RootCheck v6 = new RootCheck();
this.t = v6;
if(!v6.rootCheck()) {
StringBuffer v2 = new StringBuffer();
try {
Process v6_2 = Runtime.getRuntime().exec("ps adbd");
v6_2.waitFor();
BufferedReader v3 = new BufferedReader(new InputStreamReader(v6_2.getInputStream()));
while(true) {
String v6_3 = v3.readLine();
if(v6_3 == null) {
break;
}
v2.append(v6_3 + "\n");
}
}
catch(Exception v6_1) {
v6_1.printStackTrace();
}
if(v2.toString().indexOf("bad") != -1) {
Toast.makeText(this, "No Rooted or ADB Process Detected", 1).show();
Log.d("MainActivity", "Detection Not Rooted or ADB!");
return;
}
}
Toast.makeText(this, "Detection Rooted or ADB Process!", 1).show();
Log.d("MainActivity", String.valueOf(this.t.rootCheck()));
Log.d("MainActivity", "Detection Rooted or ADB Process!");
this.finish();
}
}
a
package c.b.a.a;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewParent;
import b.b.h.x0;
import b.h.j.n;
import c.b.a.a.l.d.b;
import c.b.a.a.l.d.c;
import c.b.a.a.l.d.e;
import c.b.a.a.l.d;
import c.b.a.a.v.g;
import c.b.a.a.v.i;
import com.hspace.pengsu.MainActivity;
import com.hspace.pengsu.RootCheck;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public final class a {
public static RootCheck a;
public static void a() {
a.a = new RootCheck();
MainActivity v0 = new MainActivity();
if(a.a.rootCheck()) {
label_43:
Log.d("CipherAlgorithm", String.valueOf(a.a.rootCheck()));
Log.d("CipherAlgorithm", "Please follow the game rules");
v0.finish();
}
else {
StringBuffer v3 = new StringBuffer();
try {
Process v1_1 = Runtime.getRuntime().exec("ps adbd");
v1_1.waitFor();
BufferedReader v4 = new BufferedReader(new InputStreamReader(v1_1.getInputStream()));
while(true) {
String v1_2 = v4.readLine();
if(v1_2 == null) {
break;
}
v3.append(v1_2 + "\n");
}
}
catch(Exception v1) {
v1.printStackTrace();
}
if(v3.toString().indexOf("bad") == -1) {
goto label_43;
}
Log.d("CipherAlgorithm", "Detection Not Rooted or ADB!");
}
String v1_3 = RootCheck.a();
"hello android world!".getBytes("UTF-8");
byte[] v0_1 = "hello android world!".getBytes();
MessageDigest v5 = MessageDigest.getInstance("MD5");
v5.update("SOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEER".getBytes());
byte[] v5_1 = v5.digest();
MessageDigest v6 = MessageDigest.getInstance("SHA-256");
v6.update(v1_3.getBytes());
byte[] v6_1 = v6.digest();
IvParameterSpec v7 = new IvParameterSpec(v5_1);
SecretKeySpec v5_2 = new SecretKeySpec(v6_1, "AES");
Cipher v6_2 = Cipher.getInstance("AES/CBC/PKCS5Padding");
v6_2.init(1, v5_2, v7);
byte[] v0_2 = v6_2.doFinal(v0_1);
if(MainActivity.v == 100) {
Log.d("CipherAlgorithm", " Decrypt Cipher : " + new String(a.d(v1_3, v1_3, Base64.decode("zem8Qf+nUSVM8gsOgKiEeZ+OPRR9EKu76gEjg2eYf4MdXK9wAXrCeTQ9r1CpWcMu".getBytes("UTF-8"), 0)), "UTF-8"));
}
else {
android.os.Process.killProcess(android.os.Process.myPid());
}
a.d("SOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEER", v1_3, v0_2);
}
public static Animator b(d arg6, float arg7, float arg8, float arg9) {
ObjectAnimator v0 = ObjectAnimator.ofObject(arg6, c.a, b.b, new e[]{new e(arg7, arg8, arg9)});
if(Build.VERSION.SDK_INT >= 21) {
e v1 = arg6.getRevealInfo();
if(v1 != null) {
Animator v6 = ViewAnimationUtils.createCircularReveal(((View)arg6), ((int)arg7), ((int)arg8), v1.c, arg9);
AnimatorSet v7 = new AnimatorSet();
v7.playTogether(new Animator[]{v0, v6});
return v7;
}
throw new IllegalStateException("Caller must set a non-null RevealInfo before calling this.");
}
return v0;
}
public static c.b.a.a.v.d c(int arg1) {
return arg1 != 0 && arg1 == 1 ? new c.b.a.a.v.e() : new i();
}
public static byte[] d(String arg2, String arg3, byte[] arg4) {
MessageDigest v0 = MessageDigest.getInstance("MD5");
v0.update(arg2.getBytes());
byte[] v2 = v0.digest();
MessageDigest v0_1 = MessageDigest.getInstance("SHA-256");
v0_1.update(arg3.getBytes());
byte[] v3 = v0_1.digest();
IvParameterSpec v0_2 = new IvParameterSpec(v2);
SecretKeySpec v2_1 = new SecretKeySpec(v3, "AES");
Cipher v3_1 = Cipher.getInstance("AES/CBC/PKCS5Padding");
v3_1.init(2, v2_1, v0_2);
return v3_1.doFinal(arg4);
}
public static float e(float arg0, float arg1, float arg2, float arg3) {
return (float)Math.hypot(((double)(arg2 - arg0)), ((double)(arg3 - arg1)));
}
public static int f(Context arg0, int arg1, int arg2) {
TypedValue v0 = a.r(arg0, arg1);
return v0 == null ? arg2 : v0.data;
}
public static int g(View arg1, int arg2) {
return a.t(arg1.getContext(), arg2, arg1.getClass().getCanonicalName());
}
public static ColorStateList h(Context arg1, TypedArray arg2, int arg3) {
if(arg2.hasValue(arg3)) {
int v0 = arg2.getResourceId(arg3, 0);
if(v0 != 0) {
ColorStateList v1 = b.b.d.a.a.a(arg1, v0);
return v1 == null ? arg2.getColorStateList(arg3) : v1;
}
}
return arg2.getColorStateList(arg3);
}
public static ColorStateList i(Context arg2, x0 arg3, int arg4) {
if(arg3.b.hasValue(arg4)) {
int v0 = arg3.b.getResourceId(arg4, 0);
if(v0 != 0) {
ColorStateList v2 = b.b.d.a.a.a(arg2, v0);
return v2 == null ? arg3.c(arg4) : v2;
}
}
return arg3.c(arg4);
}
public static Drawable j(Context arg1, TypedArray arg2, int arg3) {
if(arg2.hasValue(arg3)) {
int v0 = arg2.getResourceId(arg3, 0);
if(v0 != 0) {
Drawable v1 = b.b.d.a.a.b(arg1, v0);
return v1 == null ? arg2.getDrawable(arg3) : v1;
}
}
return arg2.getDrawable(arg3);
}
public static boolean k(Context arg1) {
return arg1.getResources().getConfiguration().fontScale >= 1.3f;
}
public static boolean l(Context arg1) {
return arg1.getResources().getConfiguration().fontScale >= 2f;
}
public static boolean m(View arg1) {
return n.m(arg1) == 1;
}
public static int n(int arg1, int arg2, float arg3) {
return b.h.d.a.a(b.h.d.a.c(arg2, Math.round(((float)Color.alpha(arg2)) * arg3)), arg1);
}
public static float o(float arg1, float arg2, float arg3) {
return arg3 * arg2 + (1f - arg3) * arg1;
}
public static PorterDuff.Mode p(int arg1, PorterDuff.Mode arg2) {
if(arg1 != 3) {
if(arg1 != 5) {
if(arg1 != 9) {
switch(arg1) {
case 14: {
break;
}
case 15: {
return PorterDuff.Mode.SCREEN;
}
case 16: {
return PorterDuff.Mode.ADD;
}
default: {
return arg2;
}
}
return PorterDuff.Mode.MULTIPLY;
}
return PorterDuff.Mode.SRC_ATOP;
}
return PorterDuff.Mode.SRC_IN;
}
return PorterDuff.Mode.SRC_OVER;
}
public static void q(AnimatorSet arg10, List arg11) {
int v0 = arg11.size();
long v2 = 0L;
int v4;
for(v4 = 0; v4 < v0; ++v4) {
Animator v5 = (Animator)arg11.get(v4);
long v6 = v5.getStartDelay();
v2 = Math.max(v2, v5.getDuration() + v6);
}
ValueAnimator v0_1 = ValueAnimator.ofInt(new int[]{0, 0});
v0_1.setDuration(v2);
arg11.add(0, v0_1);
arg10.playTogether(arg11);
}
public static TypedValue r(Context arg2, int arg3) {
TypedValue v0 = new TypedValue();
return arg2.getTheme().resolveAttribute(arg3, v0, true) ? v0 : null;
}
public static boolean s(Context arg1, int arg2, boolean arg3) {
TypedValue v1 = a.r(arg1, arg2);
return v1 != null && v1.type == 18 ? v1.data != 0 : arg3;
}
public static int t(Context arg3, int arg4, String arg5) {
TypedValue v0 = a.r(arg3, arg4);
if(v0 != null) {
return v0.data;
}
throw new IllegalArgumentException(String.format("%1$s requires a value for the %2$s attribute to be set in your app theme. You can either set the attribute in your theme or update your theme to inherit from Theme.MaterialComponents (or a descendant).", arg5, arg3.getResources().getResourceName(arg4)));
}
public static void u(View arg2, float arg3) {
Drawable v2 = arg2.getBackground();
if((v2 instanceof g)) {
g v2_1 = (g)v2;
c.b.a.a.v.g.b v0 = v2_1.b;
if(v0.o != arg3) {
v0.o = arg3;
v2_1.w();
}
}
}
public static void v(View arg2, g arg3) {
if(arg3.b.b != null && (arg3.b.b.a)) {
ViewParent v2 = arg2.getParent();
float v0 = 0f;
while((v2 instanceof View)) {
v0 += n.k(((View)v2));
v2 = v2.getParent();
}
c.b.a.a.v.g.b v2_1 = arg3.b;
if(v2_1.n != v0) {
v2_1.n = v0;
arg3.w();
}
}
}
public static PorterDuffColorFilter w(Drawable arg1, ColorStateList arg2, PorterDuff.Mode arg3) {
return arg2 == null || arg3 == null ? null : new PorterDuffColorFilter(arg2.getColorForState(arg1.getState(), 0), arg3);
}
}
RootCheck
package com.hspace.pengsu;
public class RootCheck {
public static {
System.loadLibrary("native-lib");
}
public static native String a() {
}
public native boolean rootCheck() {
}
}
중학교 3학년 때부터 형의 도움으로 Java로 프로그래밍을 시작했고 안드로이드 앱 개발하면서 선린인터넷고등학교에 진학했다. 나는 특성화고등학교라는 인식이 안 좋다기 보다는 긍정적으로 봤다. 대학 진학률도 높았고 취업도 잘되며 선후배 관계와 동아리가 정말 잘되어 있었다. 처음에 한국디지털미디어고등학교와 선린인터넷고등학교 둘 중 많은 고민을 했고 결국은 선린을 선택했다. 고등학교 입학까지 담임선생님이 많은 도움을 주셔서 아직도 정말 감사하게 생각하고 있다. 학교 면접볼 때는 첫 면접이라 그런지 정말 많이 떨었다. 면접도 잘 보지 못했지만 합격한 것만으로도 정말 감사했고 마냥 신기했다. 학교에 입학해서 진짜 누구보다 많이 놀았고 뭘 공부해야될지 혼란스럽고 방황했던 시기도 겪었다. 나는 선배들과 친구들의 도움을 받아가면서 해킹, 보안 공부도 시작했다. 단순히 멋져보였고 여러 대회에서 수상하는 모습이 존경스러웠다. 이 때 시작한 공부가 정말 재밌어서 많은 대회도 참여하고 수상하며 다른학교 친구들과도 친해지고 보안하는 사람들과도 많이 알게되면서 좋은 사람들을 많이 알게됐다. 나는 선린인터넷고 다닌걸 후회하지 않고 다시 중학교 때로 돌아간다면 다시 진학할 마음도 있다. 학교 거리가 매일 왕복 2시간씩 통학하는것만 빼면 다 좋았다. 학교 앞에 숙명여대가 있어서 놀거리도 많고 먹을것도 많아서 좋았다. 다들 놀땐 놀고 공부할땐 공부하는 분위기라 정말 최적의 학교였다. 또 외주해서 몇 십만원씩 벌어도 보고 대회 나가서 몇 백만원씩 벌고 했는데 항상 탕진했다 ㅋㅋ 먹고 놀고 옷사고 하면 항상 모자르다.. 일반고에 진학했더라면 경험하지 못할만한 재밌고 소중한 경험들을 한거같다~~<
서울여자대학교 정보보호영재교육원
중학교 3학년 때 고등심화 A 지원해서 떨어지고 고등학교 1학년 때 다시 지원해서 합격했다. 중학교 3학년 때는 아직 실력이 부족한 걸 깨닫고 다시 지원할 때는 완벽히 붙을 정도로 노력했다. 서울여대가 집에서 가까워서 다니기 버겁지는 않았지만 1년동안 격주 주말 오전 9:30 ~ 오후 4:30까지 다니는게 조금 힘들긴 했다. 함께 견학도 가고 2박 3일 집중 교육, 프로젝트, 대회 등등을 했다. 대회에서는 개인전 4등 장려상 단체전 2등으로 한국교육학술정보원장상과 테블릿PC를 받았다. 그 외에도 수료증과 반 1등으로 우수학생으로 상과 50만원도 받았다. 과분하지만 기분은 좋았다.
여기서 좋은 친구들과 선생님들을 만나서 추억도 많이 만들었다. 당시에는 조금 힘들었지만 지금 생각해보면 정말 재밌었다.
고등학교 3학년 6월에 지원해서 취약점분석트랙 교육생으로 합격하여 2021년 1월 현재까지 하고 있다. 약 2~3주 정도 준비해서 합격할 수 있었다. 준비하면서 학교 공부를 조금 놓친 부분이 있기도 하다. 이번년도 경쟁률은 거의 10:1 정도였는데 정말 많은 준비를해서 1차서류와 면접을 걸치며 합격할 수 있어서 정말 좋았다. BoB에 합격하면서 LG Gram 노트북도 제공받고 월마다 30만원정도씩 받으면서 공부를 하고 있다. 1차 교육기간 7월부터는 공통교육부터 시작해서 정말 매일 하루종일 수업을 들었다. 이 당시 코로나로 다 google meet로 수업을 하게됐는데 아쉽게도 오프라인으로 사람들과 함께 듣지 못한다는 점이 아쉬웠다. 8월까지 트랙별로 수업을 하였는데 트랙 수업에서는 심화적으로 배우기 시작했는데 많은 멘토님들이 들려주시는 이야기들과 수업들이 정말 재밌었고 어디가서 쉽게 듣지 못할만한 내용들을 전해들었다. 그리고 Compete도 해야해서 과제도 주어졌다. 이 중 80%의 과제는 해결했는데 어려워서 못한 것도 조금 있었다. 이후 2차로 프로젝트 기간이 있었는데 이 기간이 대입 시기와 겹쳤다. 그래서 솔직하게 많은 도움을 주지 못해서 팀원들에게 죄송했다. 좋은 팀원들과 멘토님들을 만났고 정말 다들 유쾌하시고 좋은 분들이였다. 우리팀은 싸우지도 않고 프로젝트를 해나갔으며 최종적으로는 많은 취약점을 찾아서 제보하며 좋게 끝났다. 그리고 TOP30에는 들지 못했지만 현재는 3차 공통교육을 받고 있다. 해킹이나 보안 공부하는 사람이라면 꼭 해볼만한 프로그램이고 좋은 멘토님들과 형들을 만날 수 있어서 좋은거 같다.
해킹과 보안에 입문하고 느낀게 알면 알수록 재밌었다. 해킹대회 CTF(Capture The Flag)에 참여하면서 문제를 풀어나가는게 흥미로웠고 고등학교 2학년 때부터 본격적으로 많은 외부 대회에 참여하고 공부하며 많은 대회에서 수상했다. 무작정 대회에 참여하면서 Top-Down 방식으로 공부했다 그래서 앞으로는 기초부터 탄탄하게 공부할 예정이다. 보안 공부하면서 모르는게 있으면 물어볼 선배들과 친구들이 있다는 점이 정말 좋았다. 물어봐도 눈치 보이지 않고 함께 공부하면서 실력도 키울 수 있어서 이보다 좋은 점이 없었다. 마냥 1학년 때는 대회에서 상타고 하는 사람들이 멋있었지만 노력하면 누구든 할 수 있다는 걸 느꼈다. 2학년 때는 Defenit 국내 해킹팀에 들어가서 좋은 사람들도 만나고 대회에 참여하며 국내, 해외 CTF에 많이 참여하며 경험을 쌓을 수 있었다. 국제 대회 참여뿐만 아니라 대회를 직접 운영, 문제 출제를 해보는 경험도 하고 재밌었다. 2021년에는 더 공부해서 팀에 기여할 수 있도록 노력해야겠다. 청소년 대회에서도 많은 수상을 하며 고등학교 2, 3학년동안 정말 알찬 2년을 보냈다. 항상 주변 지인들한테 고맙게 생각한다.
나는 수시 대부분을 특기자로 넣었다. 숭실대가 가장 먼저 합격자 발표했는데 최초합해서 다른데도 붙을줄 알았는데 다 떨어져서 아쉬운 생각이 든다. 대학 다 떨어지면 취업하려고 마음 먹고 있었다. 수능은 신청했지만 당일날 늦잠자고 환불받았다. 그리고 수험표는 받아놓고 코로나때문에 한번도 안 써봐서 아쉬웠다.
고려대 사이버국방학과(해킹방어특기자) 1차 합격 → 최종 불합격
아주대 사이버보안학과(다산인재 학생부종합) 최종 불합격
과기대 컴퓨터공학과(sw인재전형 학생부종합) 1차 탈락
부산대 정보컴퓨터공학과(sw특기자) 1차 탈락
경희대 컴퓨터공학과(sw특기자) 1차 탈락
숭실대 소프트웨어학부(sw특기자) 1차 합격 → 최초 합격
앞으로
대학교 가기전에 운전면허 따고 영어, 해킹. 알고리즘 등 다른 공부들도 열심히 해놔야겠다. 요즘 너무 공부안하고 놀기만했다 ㅋㅋ 코로나도 좀 줄어들면 좋겠다!