반응형
- 작성자: 한국인터넷진흥원 위협분석단 종합분석팀
- 배포일: 2025년 5월 12일
주의사항 해당 가이드는 Linux 시스템에서 ‘BPFDoor 악성코드’ 탐지를 지원하기 위한 명령어와 스크 립트를 포함하고 있습니다. 다만, 시스템 별 환경 차이(커널 버전, 보안 설정, 서비스 구성 등)로 인해 해당 명령어나 스크립트 실행 시, 시스템에 예기치 않은 동작 또는 오류가 발생할 수 있습 니다. 따라서 실행 전 ▲사내 보안 정책 위반 여부, ▲시스템 영향 가능성 등을 반드시 확인해 주시기 바라며, 실행으로 인해 발생하는 모든 결과 및 책임은 사용자 본인에게 있음을 안내 드립니다. |
개요
- 최근 BPFDoor 악성코드 감염 사례가 발견됨에 따라, 기업 내 보안 담당자가 스스로 감염 여부를 점 검하고 조기에 대응할 수 있도록 본 문서를 작성하였습니다.
- 본 문서는 악성코드의 특성을 분석하여, 단순한 침해 지표(IOC) 검색만으로는 확인하기 어려운 감염 흔적까지 점검할 수 있도록 가이드를 제공합니다.
BPFDoor 악성코드
- 리눅스 환경에서 포트를 열지 않고 외부 연결을 대기하는 백도어 악성코드
- 위협 행위자의 매직패킷(Magic Packet) 수신 시 셸 연결
- 리버스셸(Reverse Shell), 다이렉트 모드(바인드셸, Bind Shell) 연결
- 명령에 따라 원격지(Remote)와 셸 연결
- BPF 기술을 악용하여 네트워크 트래픽 필터 설정
- 필터 대상 : TCP, UDP, ICMP 프로토콜
- 감염 시스템에 합법적으로 열린 포트(정상 서비스) 대상 매직패킷 전송
💡 BPF(Berkeley Packet Filter) 운영체제 커널 수준에서 동작하는 네트워크 패킷 필터링 기술 네트워크 인터페이스를 통과하는 패킷을 복사하여 필터링 네트워크 성능 향상과 보안 기능 강화를 위한 목적으로 사용 |
BPFDoor 감염 여부 점검 방법 점검
- 명령어는 관리자(root) 계정 또는 권한(sudo)으로 실행해야 합니다.
- 점검 과정에서 침해 흔적 발견 시 한국인터넷진흥원에 신고하시기 바랍니다.
1. 악성코드 뮤텍스/락(Mutex/Lock) 파일 점검 : ls 명령어
- 특정 경로에 생성되는 뮤텍스/락 파일을 점검하여 악성코드 실행 여부를 점검합니다.
- 점검 대상 : /var/run/*.pid 또는 /var/run/*.lock (0 byte)
- 파일 권한(644, -rw-r--r--) 확인
- 파일 존재 시 다른 점검 방법으로 추가 검증 필요
# 명령어 1-1 : *.pid, *.lock 파일 확인
$ sudo ls -l /var/run/*.pid | awk '$5 == 0 {print $9}'
$ sudo ls -l /var/run/*.lock | awk '$5 == 0 {print $9}'
$ sudo stat -c "%a %s %n" /var/run/*.pid /var/run/*.lock 2>/dev/null | awk '$1=="6 44" && $2==0 { print $3 }'
# 명령어 1-2 : 파일 권한(644,-rw-r--r--), 파일 생성일 확인
$ sudo ls -al /var/run/.pid -rw-r--r--. 1 root root 0 Apr 28 03:17 /var/run/system.pid
2. 악성코드 자동 실행 파일 점검 : grep 명령어
- 감염 단말에 설정된 악성코드 자동 실행 파일을 점검합니다.
- 점검 대상 : /etc/sysconfig/*
- 점검 결과 : [ -f “악성코드 경로” ] && “악성코드 경로”
- 오진(정상) 가능성이 있으므로 의심 파일 대상 초동 점검(8) 및 YARA 기반 점검(9) 필요
# 명령어 2-1
$ sudo grep -Er '\[\s*-f\s+/[^]]+\]\s*&&\s*/' /etc/sysconfig/
/etc/sysconfig/test:[ -f /usr/sbin/smartadm ] && /usr/sbin/smartadm
# 명령어 2-2 : 호환성 이슈로 명령어 2-1 이 실행되지 않는 경우
$ sudo find /etc/sysconfig/ -type f -exec egrep '\[\s*-f\s+/[^]]+\]\s*&&\s*/' {} +
3. BPF(Berkeley Packet Filter) 점검 : ss 명령어
- 시스템에 등록된 BPF를 조회하여 악성코드 실행 여부를 점검합니다.
- 점검 가능 버전 : Linux Kernel 3.2 이상 + iproute2 4.0 이상
- CentOS 6.x 이하 버전에서는 확인 불가 → “3. RAW 소켓 사용 확인” 점검
- 점검 스크립트 : [붙임1] BPF 점검 스크립트 : bpfdoor_bpf.sh
# 명령어 3-1 : 서버에 등록된 BPF 필터 확인(비정상 필터 유무 점검)
$ sudo ss -0pb
# BPF 필터 내 매직넘버(Magic Sequences) 확인 → 악성코드 감염 의심
# 명령어 3-2
$ sudo ss -0pb | grep -E "21139|29269|960051513|36204|40783"
# 명령어 3-3 : 명령어 3-2로 확인 불가 시 사용
$ sudo ss -0pb | grep -EB1 "$((0x5293))|$((0x7255))|$((0x39393939))|$((0x8D6
C))|$((0x9F4F))"
- 악성코드 감염 시 출력되는 BPF 값 : 붉은색 숫자 확인
4. RAW 소켓 사용 점검 : lsof, ss 명령어
- “SOCK_RAW”, “SOCK_DGRAM” 소켓을 사용중인 프로세스를 점검합니다.
- 오진(정상) 가능성이 있으므로 의심 파일 대상 초동 점검(6) 및 YARA 기반 점검(7) 필요
- “IP type=SOCK_DGRAM“ 값 오진이 많은 경우 명령어 제외 후 점검
- 명령어 유형2 는 시스템 내 inode 전체를 탐색 하므로 부하 가능성이 존재합니다.
- (권장사항) 아래 세 가지를 만족한 경우에만 사용
- ①뮤텍스/락 파일 존재, ②BPF 점검 결과 없음, ③ RAW 소켓 명령어 4-1 결과 없음
- (권장사항) 아래 세 가지를 만족한 경우에만 사용
# 명령어 4-1
$ sudo lsof 2>/dev/null | grep -E "IP type=SOCK_RAW|IP type=SOCK_DGRAM" | a
wk '{print $2}' | sort -u | xargs -r ps -fp
UID PID PPID C STIME TTY TIME CMD
root 13851 1 0 Apr30 ? 00:00:00 dbus-daemon --system
# 명령어 4-2 : 명령어 4-1에서 진단되지 않는 경우 사용
# Linux Kernel 4.0 이상에서 점검, inode 수에 따라 시스템 부하 가능성 존재
$ sudo awk '$4=="0800" && $5=="0" {print $9}' /proc/net/packet | while read ino
de; do sudo grep -r "ino:\s*$inode" /proc/*/fdinfo/ 2>/dev/null | awk -F/ '{print
$3}' | sort -u | xargs -r sudo ps -fp; done
UID PID PPID C STIME TTY TIME CMD
root 4162 1875 0 12:31 ? 00:00:00 /usr/sbin/smartd -n -q never
# 명령어 4-3 : ss 명령어 기반 로우소켓 점검
$ sudo ss -apn | grep -E ":1 |:6 |:17 "
udp UNCONN 0 0 0.0.0.0:17 0.0.0.0:* users:(("/usr/libexec/ha",pid=36
5141,fd=4))
tcp UNCONN 0 0 0.0.0.0:6 0.0.0.0:* users:(("/usr/libexec/ha",pid=36
5141,fd=3))
- 의심 프로세스의 파일 경로를 확인합니다.
- 악성 파일이 삭제된 경우 아래와 같이 표기, 메모리에서 동작 상태
- 예시) /dev/shm/kdmtmpflush (deleted)
# 명령어 4-4
$ sudo ls -l /proc/<PID>/exe
lrwxrwxrwx. 1 root root 0 May 1 00:28 /proc/13851/exe -> /dev/shm/dbus-srv_bin
- 문자열 기반 초동 점검(6) 또는 YARA Rule 기반 점검(7)으로 악성코드 여부를 확인합니다.
5. 프로세스 환경변수 점검
- 셸(Shell) 연결 시 사용하는 악성코드의 환경변수를 점검합니다.
- 점검 스크립트 : [붙임2] 환경변수 점검 스크립트 : bpfdoor_env.sh
# 명령어 5-1
$ sudo ./bpfdoor_env.sh ([붙임2] 스크립트 사용)
[*] Starting BPFdoor environment variable manipulation detection...
Target : HOME=/tmp, HISTFILE=/dev/null, MYSQL_HISTFILE=/dev/null
Warning: Process with all suspicious environment variables detected (PID: 4076)
→ root 4076 4075 qmgr -l -t fifo -u
- 의심 프로세스의 파일 경로를 확인합니다.
# 명령어 5-2
$ sudo ls -l /proc/<PID>/exe
lrwxrwxrwx. 1 root root 0 4월 28 12:31 /proc/4076/exe -> /dev/shm/smartadm
- 문자열 기반 초동 점검(8) 또는 YARA Rule 기반 점검(9)으로 악성코드 여부를 확인합니다.
6. 특정 포트 확인 및 네트워크 장비를 이용한 패킷 점검
- 특정 네트워크 포트(port)를 사용하는지 점검
- port : 42391~43390, 8000
- 오진(정상) 가능성이 있으므로 의심 파일 대상 초동 점검(8) 및 YARA 기반 점검(9) 필요
# 명령어 6-1
$ sudo netstat -tulpn
$ sudo netstat -tulpn 2>/dev/null | awk '{match($0, /:([0-9]+)/, a); if ((a[1] >= 4239
1 && a[1] <= 43390) || $0 ~ /:8000([^0-9]|$)/) print $0}'
$ sudo netstat -tulpn 2>/dev/null | awk '$1=="tcp"&&($6=="LISTEN"||$6=="ESTA
BLISHED"){lp=substr($4,index($4,":")+1);rp=substr($5,index($5,":")+1);if((lp>=42
391&&lp<=43390)||lp==8000||(rp>=42391&&rp<=43390)||rp==8000)print}'
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 80002/abrtd
- 의심 프로세스의 파일 경로를 확인합니다.
# 명령어 6-2
$ sudo ls -l /proc/<PID>/exe
lrwxrwxrwx. 1 root root 0 May 7 00:35 /proc/80002/exe -> /home/user/control
- 문자열 기반 초동 점검(8) 또는 YARA Rule 기반 점검(9)으로 악성코드 여부를 확인합니다.
- 네트워크 장비를 이용한 패킷 점검
주요 특징 BPFdoor 매직패킷을 감염 단말에 전송 : 24byte(UDP, TCP) , 44byte(ICMP) , 100byte 이하 (TCP:HTTP POST) - 전체 패킷 크기가 아닌 페이로드 크기 - 일부 악성코드의 경우 HTTP 요청 값 수신 : TCP 마커(Marker) : HTTP POST Request-URI 내 문자열 값 9999 확인 페이로드 : BODY의 Base16 디코딩 값 - 페이로드 내 매직 시퀀스(sequences), 비밀번호(password) 존재 - 매직 시퀀스 : UDP, ICMP( 0x7255 , 0x9F4F ), TCP( 0x5293 , 0x39393939 , 0x8D6C ) |
- TCP : HTTP POST Request
- HTTP POST Request-URI에서 마커(Marker) 값 9999 (string) 존재 확인
- 외부 ↔ 내부, 내부 ↔ 내부 간 통신 구간에서 URI 또는 User-Agent 값 점검
- BODY 값을 Base16 디코딩하여 페이로드로 사용
- HTTP POST Request-URI에서 마커(Marker) 값 9999 (string) 존재 확인
<HTTP POST Request-URI 값>
/admin/login.aspx?id=99990
/admin_login.aspx?id=99990
/Admin/Default.aspx?=99990
/UploadFile.aspx?id=099990
/user/admin.php?id=0099991
/uploadfiles.php?id=099991
/uploadfilm.php?id=0099991
/uploadphoto.php?id=099991
/uploadPic.php?id=00099991
/systems/login.php?i=99991
<User-Agent 값>
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHT
ML, like Gecko) Chrome/90.0.5389.90 Safari/537.36
BPFDoor 컨트롤러 점검 방법
- 컨트롤러(Controller)는 BPFDoor에 감염된 단말을 제어하기 위해 사용하는 악성 파일입니다.
7. 실행중인 프로세스명 점검 : ps 명령어
- 악성코드의 위장 프로세스명을 확인합니다.
- 오진(정상) 가능성이 있으므로 의심 파일 대상 초동 점검(8) 및 YARA 기반 점검(9) 필요
- 비정상 프로세스 판단 기준
- 의심 프로세스명 : /usr/sbin/abrtd , /sbin/udevd , cmathreshd, /sbin/sgaSolAgent , /usr/sbin/atd , pickup
- 명령어 7-2를 실행하여 파일 경로와 프로세스명의 동일여부 확인(동일한 경우 정상, 동 일하지 않은 경우 비정상 의심)
# 명령어 7-1(의심 프로세스 동작여부 확인)
$ sudo ps -ef | grep -E '/usr/sbin/abrtd|/sbin/udevd|cmathreshd|/sbin/sgaSolAgen
t|/usr/sbin/atd|pickup'
root 25469 3568 0 19:18 pts/0 00:00:00 /usr/sbin/abrtd
# 명령어 7-2(예시: 비정상 의심 프로세스)
$ sudo ls -l /proc/<PID>/exe
lrwxrwxrwx. 1 root root 0 4월 29 19:19 /proc/25469/exe -> /dev/shm/controller
- 문자열 기반 초동 점검(8) 또는 YARA Rule 기반 점검(9)으로 악성코드 여부를 확인합니다.
악성 의심 파일 점검 방법
8. 문자열 기반 초동 점검 : strings 명령어
- 악성코드가 사용하는 문자열 패턴을 기반으로, 의심 파일을 초기 단계에서 신속히 점검합니다.
- YARA 도구가 설치되지 않은 환경에서 초동으로 악성 의심 판단
- 악성 의심파일 1차 선별 → 점검(임시) 디렉토리로 복사 → strings 명령 실행
- 초동 점검에서 문자열 패턴 확인 시 악성 파일을 채증하여 YARA 도구로 2차 검증 수행
- 초동 점검은 오진 가능성이 있으며, 반드시 2차 YARA 검증이 필요합니다.
# 명령어 8-1 : 단일 파일(strings) : 권장사항
$ sudo strings -a -n 5 <의심파일 경로> | grep -E 'MYSQL_HISTFILE=/dev/null|:h:d:l:
s:b:t:|:f:wiunomc|:f:x:wiuoc|ttcompat'
/dev/ptmH
ttcompat
# 명령어 8-2 : 특정 경로(find), filesize : 15K~4M, 검색 깊이 1, "권장하지 않음"
# 출력 결과 [파일명]: 매칭 문자열
$ sudo find <의심경로> -maxdepth 1 -type f -size +15k -size -4M -exec sh -c 'strin
gs -a -n5 "$1"|sed "s|^|$1: |"|grep -E "MYSQL_HISTFILE=/dev/null|:h:d:l:s:b:t:|:f:wi
unomc|:f:x:wiuoc|ttcompat"' _ {} \;
./dbus-srv-bin: ttcompat
./manx: export MYSQL_HISTFILE=/dev/null
./manx: :h:d:l:s:b:t:D:g:H:f:wiunomcv
9. YARA Rule 기반 점검
- 악성코드 의심 파일을 선별하여 YARA 도구와 룰로 점검합니다.
- 적용룰 : [붙임3] BPFDoor YARA Rule : bpfdoor.yar
- 특정 디렉토리를 대상으로 YARA 도구를 사용할 경우 시스템 장애가 발생할 수 있습니다.
- 디렉토리 내부의 바이너리 파일을 외부 또는 다른 경로에 복사하여 점검 필요
[붙임1] BPF 점검 스크립트 : bpfdoor_bpf.sh
- BPF를 설정한 프로세스 정보(프로세스명, PID, 실행 경로) 출력
#!/bin/bash
echo "[*] Detecting processes with active BPF usage..."
# 1. Extract PIDs directly from ss output
sudo ss -0pb | grep -oP 'pid=\K[0-9]+' | sort -u | while read pid; do
# 2. For each PID, find the executable path
if [[ -e "/proc/$pid" ]]; then
exe_path=$(readlink -f /proc/$pid/exe 2>/dev/null)
proc_name=$(cat /proc/$pid/comm 2>/dev/null)
echo ""
echo "Process Name: ${proc_name:-Unknown}, PID: $pid"
echo " → Executable: ${exe_path:-Not found}"
fi
done
[붙임2] 환경변수 점검 스크립트 : bpfdoor_env.sh
- 악성코드의 가상터미널(PTY), 셸의 특정 환경 변수를 사용하는 프로세스 출력
#!/bin/bash
echo "echo [*] Detecting processes with BPFDoor environment variable manipulati
on..."
echo "Target : HOME=/tmp, HISTFILE=/dev/null, MYSQL_HISTFILE=/dev/null"
CHECK_ENV=("HOME=/tmp" "HISTFILE=/dev/null" "MYSQL_HISTFILE=/dev/null")
# Process scanning
for pid in $(ls /proc/ | grep -E '^[0-9]+$'); do
if [ -r /proc/$pid/environ ]; then
env_data=$(tr '\0' '\n' < /proc/$pid/environ)
match_all=true
for check_item in "${CHECK_ENV[@]}"; do
if ! echo "$env_data" | grep -q "$check_item"; then
match_all=false
break
fi
done
if [ "$match_all" = true ]; then
echo "Warning: Process with all suspicious environment variables detected
(PID: $pid)"
echo " → $(ps -p $pid -o user=,pid=,ppid=,cmd=)"
echo ""
fi
fi
done
[붙임3] BPFDoor YARA Rule : bpfdoor.yar
- BPFDoor 탐지 : ELF_BPFDoor BPFDoor
- 컨트롤러 탐지 : ELF_BPFDoor_Controller
rule ELF_BPFDoor
{
meta:
description = "BPFDoor Malware(ELF) Detection rule"
author = "KrCERT/CC Threat Hunting Analysis Team"
date = "2025-05-06"
hash = "c7f693f7f85b01a8c0e561bd369845f40bff423b0743c7aa0f4c323d91
33b5d4"
hash = "3f6f108db37d18519f47c5e4182e5e33cc795564f286ae770aa033721
33d15c4"
hash = "95fd8a70c4b18a9a669fec6eb82dac0ba6a9236ac42a5ecde270330
b66f51595"
hash = "aa779e83ff5271d3f2d270eaed16751a109eb722fca61465d86317e03b
bf49e4"
ver = "1.1"
strings:
$pty_1 = "/dev/ptm"
$pty_2 = "ptem"
$pty_3 = "ldterm"
$pty_4 = "ttcompat"
// for ( i = 0xA597; i <= 0xA97E; ++i )
$bind_port_1 = {C7 45 ?? 97 A5 00 00 EB}
$bind_port_2_1 = {83 45 ?? 01 81 7D ?? 7E A9 00 00 7E}
$bind_port_2_2 = {81 7D ?? 7E A9 00 00 7E}
// v1.1 : added new pattern "PS1=[\\u@\\h : "
$ps1 = {C6 85 ?? ?? FF FF 50 C6 85 ?? ?? FF FF 53 C6 85 ?? ?? FF FF 31 C6 8
5 ?? ?? FF FF 3D C6 85 ?? ?? FF FF 5B C6 85 ?? ?? FF FF 5C C6 85 ?? ?? FF FF 75
C6 85 ?? ?? FF FF 40 C6 85 ?? ?? FF FF 5C C6 85 ?? ?? FF FF 68}
// v1.1 : bpf filter modify (dbus, hald, trend-B, Trend-E)
$bpf_filter_1 = {B1 00 00 00 0E 00 00 00 48 00 00 00 16 00 00 00 15 00 ?? ??
?? ?? 00 00 15 00 00 07 01 00 00 00 28 00 00 00 14 00 00 00 45 00 (11|1A) 00 FF
1F 00 00}
$bpf_filter_2 = {07 00 00 00 00 00 00 00 (40|48) 00 00 00 00 00 00 00 02 0
0 00 00 (00|01|03) 01 00 00 00 00 00 00 00 ?? ?? ?? ?? 02 00 00 00 (01|02|04) 0
0 00 00 61 00 00 00 (01|02|04) 00 00 00}
$bpf_filter_3 = {07 00 00 00 00 00 00 00 40 00 00 00 0E 00 00 00 15 00 00
01 39 39 39 39 06 00 00 00 FF FF 00 00 06 00 00 00 00 00 00 00}
$bpf_filter_4 = {48 00 00 00 10 00 00 00 15 00 01 00 BB 01 00 00 15 00 00 01
16 00 00 00 06 00 00 00 00 00 04 00 06 00 00 00 00 00 00 00}
// I5*AYbs@LdaWbsO
$md5_salt = {C6 45 ?? 49 C6 45 ?? 35 C6 45 ?? 2A C6 45 ?? 41 C6 45 ?? 59
C6 45 ?? 62 C6 45 ?? 73 C6 45 ?? 40 C6 45 ?? 4C C6 45 ?? 64 C6 45 ?? 61 C6 45
?? 57 C6 45 ?? 62 C6 45 ?? 73 C6 45 ?? 4F}
// qmgr -l -t fifo
$pname = {C6 ?? ?? ?? FF FF 71 C6 ?? ?? ?? FF FF 6D C6 ?? ?? ?? FF FF 67 C6
?? ?? ?? FF FF 72 C6 ?? ?? ?? FF FF 20 C6 ?? ?? ?? FF FF 2D C6 ?? ?? ?? FF FF 6C
C6 ?? ?? ?? FF FF 20 C6 ?? ?? ?? FF FF 2D C6 ?? ?? ?? FF FF 74 C6 ?? ?? ?? FF FF
20 C6 ?? ?? ?? FF FF 66 C6 ?? ?? ?? FF FF 69 C6 ?? ?? ?? FF FF 66 C6 ?? ?? ?? FF
FF 6F}
$solaris_1 = "(udp[8:2]=0x7255) or (icmp[8:2]=0x7255)"
$solaris_2 = "HISTFILE=/dev/null"
$solaris_3 = "MYSQL_HISTFILE=/dev/null"
condition:
uint32(0) == 0x464C457F and
(
(all of ($pty*) and (2 of ($bind_port*) or $ps1)) or // v1.1
((all of ($pty*) or $ps1) and 2 of ($bind_port*)) or // v1.1
(1 of ($bpf_filter*)) or
($md5_salt or $pname) or
(all of ($solaris*))
)
}
rule ELF_BPFDoor_Controller
{
meta:
description = "BPFDoor Malware(ELF) Controller Detection rule"
author = "KrCERT/CC Threat Hunting Analysis Team"
date = "2025-05-06"
hash = "93f4262fce8c6b4f8e239c35a0679fbbbb722141b95a5f2af53a2bcaf
e4edd1c"
hash = "1925e3cd8a1b0bba0d297830636cdb9ebf002698c8fa71e006358120
4f4e8345"
hash = "591198c234416c6ccbcea6967963ca2ca0f17050be7eed1602198308
d9127c78"
ver = "1.1"
strings:
// v1.1 : added new pattern
$pname = /\/usr\/sbin\/[a-z]{2,8}/
$str_1 = "[-] option requires an argument -- d"
$str_2 = ":h:d:l:s:b:t:"
// mov cs:magic_flag, 5571h
$magic = {C7 05 ?? ?? ?? 00 71 55 00 00}
$env_1 = "export TERM=vt100"
$env_2 = "export MYSQL_HISTFILE=/dev/null"
$env_3 = "export HISTFILE=/dev/null"
$env_4 = "unset PROMPT_COMMAND"
$env_5 = "export HISTSIZE=100"
condition:
uint32(0) == 0x464C457F and
($pname or 1 of ($str*)) and $magic and (all of ($env*))
}
반응형
'IT 관련 > 보안공지' 카테고리의 다른 글
민생회복 소비쿠폰 지급 사칭 스미싱, 피싱 대응법 (10) | 2025.07.10 |
---|---|
SK텔레콤 해킹 2차 발표 핵심 정리(3년전 시작된 해킹) (1) | 2025.05.22 |
SKT 해킹 이슈를 악용한 피싱 주의 권고 (12) | 2025.05.12 |